Core Text Rotation 无法正确旋转 - Swift
Core Text Rotation does not properly rotate - Swift
我正在尝试旋转 Core Text,使其可读,尽管它是通过旋转的上下文生成的。
我的问题是,无论旋转方法如何,生成的文本都不是预期的。
这里是工作场地:
import Foundation
import UIKit
import XCPlayground
class ClockFace: UIView {
func drawText(context: CGContextRef, text: NSString, attributes: [String: AnyObject], x: CGFloat, y: CGFloat, align: 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)
CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(align * 43.0))
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))
if (i % 5 == 0) {
nums++
drawText(ctx!, text: "\(nums)", attributes: [NSForegroundColorAttributeName : UIColor.blackColor().CGColor, NSFontAttributeName : UIFont.systemFontOfSize(12)], x: 42, y: 0, align: CGFloat(6.0 * Double(i) * M_PI / 180))
}
CGContextRestoreGState(ctx)
}
}
}
let myView = ClockFace(frame: CGRectMake(0, 0, 150, 150))
myView.backgroundColor = .lightGrayColor()
XCPShowView("", view: myView)
无论 CGAffineTransfomMakeRotation 中的值如何,文本都难以辨认。
这是为什么?我是否正确旋转了文本?
此致,布兰登
我根据你的代码画了一个钟面,但做了一些修改。
基本上我所做的是将整个钟面翻转并移动到 for 循环之外。你可以看到我将 CGContextTranslateCTM()
和 CGContextScaleCTM()
从 drawText()
移动到了 drawRect()
。其他是由于上述修改导致的一些小的计算变化。
至于CGContextSetTextMatrix()
,这里发生的旋转影响每个字符而不是整个字符串。您可以注释第 19 和 20 行并取消注释第 21 行以获得不同的结果,看看我的意思。
此外,如果您想直接获取 playground 文件,可以从 here 下载。
import Foundation
import UIKit
import XCPlayground
class ClockFace: UIView {
func drawText(context: CGContextRef, text: String, attributes: [String: AnyObject], x: CGFloat, y: CGFloat, align: CGFloat) -> CGSize {
let font = attributes[NSFontAttributeName] as! UIFont
let attributedString = NSAttributedString(string: text, 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)
var transform = CGAffineTransformMakeTranslation(x + 10, y + font.descender)
transform = CGAffineTransformRotate(transform, align)
//CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(align))
CGContextConcatCTM(context, transform);
CTFrameDraw(frame, context)
return textSize
}
override func drawRect(rect: CGRect) {
let ctx: CGContext? = UIGraphicsGetCurrentContext()
CGContextTranslateCTM(ctx, -45, rect.size.height + 5)
CGContextScaleCTM(ctx, 1, -1)
var nums: Int = 2
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))
if (i % 5 == 0) {
nums++
nums = nums > 12 ? nums - 12 : nums
drawText(ctx!, text: "\(nums)", attributes: [NSForegroundColorAttributeName : UIColor.whiteColor(), NSFontAttributeName : UIFont.systemFontOfSize(12)], x: 42, y: 0, align: CGFloat(6.0 * Double(i) * M_PI / 180))
}
CGContextRestoreGState(ctx)
}
}
}
let view = ClockFace(frame: CGRectMake(0, 0, 150, 150))
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
XCPlaygroundPage.currentPage.liveView = view
我正在尝试旋转 Core Text,使其可读,尽管它是通过旋转的上下文生成的。
我的问题是,无论旋转方法如何,生成的文本都不是预期的。
这里是工作场地:
import Foundation
import UIKit
import XCPlayground
class ClockFace: UIView {
func drawText(context: CGContextRef, text: NSString, attributes: [String: AnyObject], x: CGFloat, y: CGFloat, align: 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)
CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(align * 43.0))
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))
if (i % 5 == 0) {
nums++
drawText(ctx!, text: "\(nums)", attributes: [NSForegroundColorAttributeName : UIColor.blackColor().CGColor, NSFontAttributeName : UIFont.systemFontOfSize(12)], x: 42, y: 0, align: CGFloat(6.0 * Double(i) * M_PI / 180))
}
CGContextRestoreGState(ctx)
}
}
}
let myView = ClockFace(frame: CGRectMake(0, 0, 150, 150))
myView.backgroundColor = .lightGrayColor()
XCPShowView("", view: myView)
无论 CGAffineTransfomMakeRotation 中的值如何,文本都难以辨认。
这是为什么?我是否正确旋转了文本?
此致,布兰登
我根据你的代码画了一个钟面,但做了一些修改。
基本上我所做的是将整个钟面翻转并移动到 for 循环之外。你可以看到我将 CGContextTranslateCTM()
和 CGContextScaleCTM()
从 drawText()
移动到了 drawRect()
。其他是由于上述修改导致的一些小的计算变化。
至于CGContextSetTextMatrix()
,这里发生的旋转影响每个字符而不是整个字符串。您可以注释第 19 和 20 行并取消注释第 21 行以获得不同的结果,看看我的意思。
此外,如果您想直接获取 playground 文件,可以从 here 下载。
import Foundation
import UIKit
import XCPlayground
class ClockFace: UIView {
func drawText(context: CGContextRef, text: String, attributes: [String: AnyObject], x: CGFloat, y: CGFloat, align: CGFloat) -> CGSize {
let font = attributes[NSFontAttributeName] as! UIFont
let attributedString = NSAttributedString(string: text, 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)
var transform = CGAffineTransformMakeTranslation(x + 10, y + font.descender)
transform = CGAffineTransformRotate(transform, align)
//CGContextSetTextMatrix(context, CGAffineTransformMakeRotation(align))
CGContextConcatCTM(context, transform);
CTFrameDraw(frame, context)
return textSize
}
override func drawRect(rect: CGRect) {
let ctx: CGContext? = UIGraphicsGetCurrentContext()
CGContextTranslateCTM(ctx, -45, rect.size.height + 5)
CGContextScaleCTM(ctx, 1, -1)
var nums: Int = 2
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))
if (i % 5 == 0) {
nums++
nums = nums > 12 ? nums - 12 : nums
drawText(ctx!, text: "\(nums)", attributes: [NSForegroundColorAttributeName : UIColor.whiteColor(), NSFontAttributeName : UIFont.systemFontOfSize(12)], x: 42, y: 0, align: CGFloat(6.0 * Double(i) * M_PI / 180))
}
CGContextRestoreGState(ctx)
}
}
}
let view = ClockFace(frame: CGRectMake(0, 0, 150, 150))
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
XCPlaygroundPage.currentPage.liveView = view