简体   繁体   English

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

[英]How to rotate text in NSView? (Mac OS, Cocoa, Swift)

I am new to Cocoa/Swift applications for Mac OS 10.11 (Not iOS). 我是Mac OS 10.11(不是iOS)的Cocoa / Swift应用程序的新手。 I created an NSView with the size of A4 paper, drew some simple lines and some text using NSString.drawAtPoint within drawRect() . 我创建了一个大小为A4纸的NSView ,并在drawRect()使用NSString.drawAtPoint绘制了一些简单的线条和一些文本。 So far it works. 到目前为止,它仍然有效。

However, from time to time, I need a few characters to be turned 90 degrees, and some text needs to be scaled at X, or Y direction. 但是,有时我需要将几个字符旋转90度,并且一些文本需要在X或Y方向上缩放。 That is where I don't know how to do it. 那是我不知道怎么做的地方。 Please can someone tell me how to achieve these? 请有人告诉我如何实现这些目标?

Many thanks. 非常感谢。

You can use NSAffineTransform . 您可以使用NSAffineTransform This code draws a capital "A" rotated 90 degrees clockwise: 这段代码绘制了一个顺时针旋转90度的大写字母“ A”:

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

Note that rotateByDegrees rotates the graphics context around the origin point. 请注意, rotateByDegrees会围绕原点旋转图形上下文。 If you want to rotate around some other point, you need to add a couple of translations. 如果要绕其他点旋转,则需要添加几个平移。 This concat sa transform that rotates around rotatePoint : concat sa转换围绕rotatePoint旋转:

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

Here is similar answer using Swift 3.1 for cocoa / macOS. 这是将Swift 3.1用于可可/ macOS的类似答案。 Some convenience methods have been added to the graphic context in order to apply rotation and other common transformations, without having to create a separate AffineTransform. 一些便捷方法已添加到图形上下文中,以便应用旋转和其他常见转换,而不必创建单独的AffineTransform。

The real trick to remember here, is that when you rotate the context, you are rotating the entire coordinate system, so you have to translate the point at which you want to draw the text in the non-rotated context, to an overlapping point in the rotated context. 这里要记住的真正技巧是,旋转上下文时,您正在旋转整个坐标系,因此必须将要在非旋转上下文中绘制文本的点转换为旋转的上下文。

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 )
}

Here is what the call would look like in your NSView: 这是您的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!)

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM