我使用下面的代码在图片的右侧绘制文字。
im.lockFocus()
if let context = NSGraphicsContext.current?.cgContext {
context.saveGState()
let size = text.size(withAttributes: textFontAttributes)
context.translateBy(x: imageRect.width-size.height, y: (imageRect.height - size.width) / 2)
context.rotate(by: CGFloat.pi / 2)
text.draw(at: .zero, withAttributes: textFontAttributes)
context.restoreGState()
im.unlockFocus()
如你所见,从右侧开始有一些过大的间距,我该如何解决?
更新。
class DemoView: NSView {
override func draw(_ rect: NSRect) {
// .. your drawing code here
NSColor.red.set() // just for demo
rect.fill() // just for demo
if let context = NSGraphicsContext.current?.cgContext {
context.saveGState()
let text: NSString = "Hello World"
let attributes = [
NSAttributedString.Key.foregroundColor: NSColor.white,
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 24)
]
let size = text.size(withAttributes: attributes)
context.translateBy(x: imageRect.width-size.height, y: (rect.height - size.width) / 2)
context.rotate(by: CGFloat.pi / 2)
text.draw(at: .zero, withAttributes: attributes)
context.restoreGState()
}
}
}
希望你能明白CGContext变换的工作原理,如果不明白,就学习一下吧。
你的问题最简单的一个实现是这样的:文字是蓝色的矩形,你想画一个红色的矩形。
所以计算一个移位变换,然后旋转90就可以了。在这种情况下,移位变换是蓝色矩形的左下角,同时也是红色矩形的右下角。
你的 DemoView
可以是这样的。
class DemoView: NSView {
override func draw(_ rect: NSRect) {
let image = NSImage(named: "test_image.jpg")!
if let context = NSGraphicsContext.current?.cgContext {
context.saveGState()
NSColor.red.set() // just for demo
rect.fill() // just for demo
image.draw(in: rect)
let text: NSString = "Hello World"
let attributes = [
NSAttributedString.Key.foregroundColor: NSColor.white,
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 24)
]
let size = bounds.size
let rotatedTextCenter = CGPoint(x: size.width*0.8, y: size.height/2)
// draw the the circle in desired center to check if text was transformed correctly
drawCircleInView(context: context, center: rotatedTextCenter)
// draw the rotated text so its center fits the circle center
drawAttributedTextInView(text: text, textAttributes: attributes, context: context, viewSize: size, centerInView: rotatedTextCenter)
context.restoreGState()
}
}
func drawCircleInView(context: CGContext, center: CGPoint) {
context.setLineWidth(5)
context.setFillColor(NSColor.red.cgColor)
context.addArc(center: center, radius: 10, startAngle: 0, endAngle: CGFloat.pi*2, clockwise: false)
context.fillPath()
}
func drawAttributedTextInView(text: NSString,
textAttributes: [NSAttributedString.Key:Any],
context: CGContext,
viewSize: CGSize,
centerInView textCenter: CGPoint) {
// we assume everything else was already drawn and context has identity transform for the simplicity
let textSize = text.size(withAttributes: textAttributes)
context.translateBy(x: textCenter.x+textSize.height/2, y: textCenter.y-textSize.width/2)
context.rotate(by: CGFloat.pi / 2)
text.draw(at: .zero, withAttributes: textAttributes)
}
}
在这段代码中 centerInView
param是红色矩形的中心。
请注意,我们用红色填满整个视图, 然后渲染图像,再渲染文本。没有过多的间距存在。如果有的话,我们会看到红色的线条。下面 的图像。
您可以下载演示 此处.
还有,请不要画 一切 一下 draw(_ rect: NSRect)
调用--至少尝试提取文本绘制func--它将使你在定义问题的变量时更加灵活。
更新:
我需要将文本 "翻转",使其底部指向中心,变换后的文本可以是这样的。
context.translateBy(x: textCenter.x-textSize.height/2, y: textCenter.y+textSize.width/2)
context.rotate(by: -CGFloat.pi / 2)