如何在NSView中旋转文本? (Mac OS,Cocoa,Swift)

时间:2016-07-16 09:22:06

标签: swift macos cocoa

我是Mac OS 10.11(非iOS)的Cocoa / Swift应用程序的新手。我创建了NSView,其大小为A4纸张,在NSString.drawAtPoint中使用drawRect()绘制了一些简单的线条和一些文字。到目前为止它的确有效。

然而,有时我需要将几个字符转为90度,而某些文字需要在X或Y方向缩放。这是我不知道该怎么做的地方。请有人能告诉我如何实现这些目标吗?

非常感谢。

2 个答案:

答案 0 :(得分:3)

您可以使用NSAffineTransform。此代码将大写字母“A”顺时针旋转90度:

[NSGraphicsContext saveGraphicsContext]; // save current affine transform
[[[NSAffineTransform transform] rotateByDegrees:90] concat];
[@"A" drawAtPoint:point withAttributes:@{}];
[NSGraphicsContext restoreGraphicsContext]; // restore original transform

请注意rotateByDegrees围绕原点旋转图形上下文。如果要围绕其他点旋转,则需要添加几个翻译。这个concat变换围绕rotatePoint旋转:

NSAffineTransform *transform = [NSAffineTransform transform];
[transform translateXBy:rotatePoint.x yBy:rotatePoint.y];
[transform rotateByDegrees:90];
[transform translateXBy:-rotatePoint.x yBy:-rotatePoint.y];
[transform contat];

答案 1 :(得分:1)

以下是使用Swift 3.1 for cocoa / macOS的类似答案。为了应用旋转和其他常见变换,在图形上下文中添加了一些便捷方法,而无需创建单独的AffineTransform。

这里要记住的真正诀窍是,当您旋转上下文时,您正在旋转整个坐标系,因此您必须将要在非旋转上下文中绘制文本的点转换为旋转上下文中的重叠点。

func drawVerticalText(text: String, withAttributes attributes: [String : Any]?, origin: CGPoint, context: CGContext) {

    // Draws text that rotated 90 degrees ( pi/2 radians ) counterclockwise.

    /*

    Rotate entire drawing context 90 degrees clockwise including axis orientation!
    i.e. the positive Y axis is pointing to the left instead of up, and positive X axis
    is pointing up instead of to the right.  This also means that anything drawn having
    two positive x and y coordinates will be rendered off screen of the current view.

    */

    let halfRadian : CGFloat = CGFloat.pi / 2.0

    context.rotate(by: halfRadian )

    /*

    In order to have the text rendered in our current view, we have to find a point in our
    rotated context, that overlays the point where we want to draw the text in our non-rotated
    context. The x-axis is horizontal in the non-rotated context (ascending values to the
    right), while the y-axis is horizontal in our rotated context (ascending values to the
    left).  So our oppisite value of our x coordinate in the non-rotated context must be 
    mapped to the y-axis in our rotated context.  Accordingly, the y-axis is vertical in our
    non-rotated context (ascending values upwards), while x-axis is vertical in our rotated 
    context (ascending values upwards). So our y value in the non-rotated context must be 
    mapped to the x-axis in our rotated context. i.e. If we graph a point (Y,-X) in our rotated 
    context, it will overlap the point (X,Y) in our non-rotated context.

    */

    // The origin represents the lower left corner of the rectangle in which the text will be rendered.

    let translatedOrigin = NSPoint(x: origin.y, y: -origin.x)

    // Draw the text.

    text.draw(at: translatedOrigin, withAttributes: attributes)

    // Rotate the context counter-clockwise 90 degrees ( pi/2 radians ) after we are done.

    context.rotate(by: -halfRadian )
}

以下是NSView中的调用内容:

override func draw(_ dirtyRect: NSRect) {
    super.draw(dirtyRect)

    let context = NSGraphicsContext.current()?.cgContext

    drawVerticalText(text: "My text string", withAttributes: nil, origin: CGPoint(x: 50.0, y: 100.0)  , context: context!)

}