【问题标题】:How to Rotate Core Text with Swift?如何使用 Swift 旋转核心文本?
【发布时间】:2016-05-24 15:35:01
【问题描述】:

我正在尝试使用 CoreGraphics 制作模拟时钟。

我的问题是我不知道如何旋转数字的文本。

代码的大致流程如下:

首先我旋转上下文,然后,如果适用,我画一个数字;重复。

完整的游乐场

import UIKit
import Foundation
import XCPlayground

class ClockFace: UIView {
    func drawText(context: CGContextRef, text: NSString, attributes: [String: AnyObject], x: CGFloat, y: CGFloat) -> CGSize {
        CGContextTranslateCTM(context, 0, 0)
        CGContextScaleCTM(context, 1, -1)
        let font = attributes[NSFontAttributeName] as! UIFont
        let attributedString = NSAttributedString(string: text as String, attributes: attributes)

        let textSize = text.sizeWithAttributes(attributes)

        let textPath    = CGPathCreateWithRect(CGRect(x: -x, y: y + font.descender, width: ceil(textSize.width), height: ceil(textSize.height)), nil)
        let frameSetter = CTFramesetterCreateWithAttributedString(attributedString)
        let frame       = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: attributedString.length), textPath, nil)

        CTFrameDraw(frame, context)

        return textSize
    }

    override func drawRect(rect: CGRect) {
        let ctx: CGContext? = UIGraphicsGetCurrentContext()
        var nums: Int = 0
        for i in 0..<60 {
            CGContextSaveGState(ctx)
            CGContextTranslateCTM(ctx, rect.width / 2, rect.height / 2)
            CGContextRotateCTM(ctx, CGFloat(6.0 * Double(i) * M_PI / 180))
            CGContextMoveToPoint(ctx, 72, 0)
            if (i % 5 == 0) {
                nums++
                drawText(ctx!, text: "\(nums)", attributes: [NSForegroundColorAttributeName : UIColor.blackColor().CGColor, NSFontAttributeName : UIFont.systemFontOfSize(12)], x: 42, y: 0)
            }
            CGContextRestoreGState(ctx)
        }

    }
}
let myView = ClockFace(frame: CGRectMake(0, 0, 150, 150))
myView.backgroundColor = .lightGrayColor()
XCPShowView("", view: myView)

因此我的问题是,如何使用 Swift 旋转 Core Text?

【问题讨论】:

    标签: ios swift macos rotation core-graphics


    【解决方案1】:

    您可以通过CGContextSetTextMatrix() 实现CGAffineTransform 来旋转文本。例如:

    ...
    let frame = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: attributedString.length), textPath, nil)
    CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(CGFloat(M_PI)))
    CTFrameDraw(frame, context)
    

    【讨论】:

    • context.textMatrix = CGAffineTransform.init(rotationAngle: CGFloat.pi) ---(CGContextSetTextMatrix已被移除,设置上下文的文本矩阵属性)
    【解决方案2】:

    这 15 行代码花了我 8 个多小时,大量 StackOverflow 搜索(许多答案没有/不再有效!),才弄明白。

    注意使用 CTLineDraw 的解决方案。对于 CTLineDraw,您必须更改 cgContext.textMatrix 才能进行旋转,我得到了非常奇怪/不可靠的结果。生成一个框架然后旋转该框架被证明更加可靠。

    使用 Swift 5.2...

    func drawCenteredString(
        cgContext: CGContext,
        string: String,
        targetCenter: CGPoint,
        angleClockwise: Angle,
        uiFont: UIFont
    ) {
        let attrString = NSAttributedString(string: string, attributes: [NSAttributedString.Key.font: uiFont])
        let textSize = attrString.size()
        let textPath = CGPath(rect: CGRect(x: CGFloat(-textSize.width/2), y: -uiFont.ascender / 2, width: ceil(textSize.width), height: ceil(textSize.height)), transform: nil)
        let frameSetter = CTFramesetterCreateWithAttributedString(attrString)
        let frame = CTFramesetterCreateFrame(frameSetter, CFRange(location: 0, length: attrString.length), textPath, nil)
        cgContext.saveGState()
        cgContext.translateBy(x: targetCenter.x, y: targetCenter.y)
        cgContext.scaleBy(x: 1, y: -1)
        cgContext.rotate(by: CGFloat(-angleClockwise.radians))
        CTFrameDraw(frame, cgContext)
        cgContext.restoreGState()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-21
      • 2011-06-30
      • 1970-01-01
      • 2020-08-09
      相关资源
      最近更新 更多