swift - 使用 Swift 在 NSView 中使用图层时如何绘制文本
问题描述
我在我的 NSView 中使用图层,因为大部分显示不会经常更改。这工作正常。我现在正要向图层添加文本。这是行不通的。
要绘制文本,我正在尝试使用另一个答案中的代码来了解如何在曲线上绘制文本。我已经研究过,但我尝试过的没有任何帮助。我创建了一个 Playground 来演示。当我运行 Playground 时,我可以看到实际调用了显示文本的代码,但屏幕上没有呈现任何内容。我确定我有什么问题,只是不确定是什么。
下面是操场,以及上面引用的代码(针对 Swift 5、NS* 与 UI* 进行了更新,并删除了大小的注释)。
import AppKit
import PlaygroundSupport
func centreArcPerpendicular(text str: String,
context: CGContext,
radius r: CGFloat,
angle theta: CGFloat,
colour c: NSColor,
font: NSFont,
clockwise: Bool){
let characters: [String] = str.map { String($0) }
let l = characters.count
let attributes = [NSAttributedString.Key.font: font]
var arcs: [CGFloat] = []
var totalArc: CGFloat = 0
for i in 0 ..< l {
arcs += [chordToArc(characters[i].size(withAttributes: attributes).width, radius: r)]
totalArc += arcs[i]
}
let direction: CGFloat = clockwise ? -1 : 1
let slantCorrection: CGFloat = clockwise ? -.pi / 2 : .pi / 2
var thetaI = theta - direction * totalArc / 2
for i in 0 ..< l {
thetaI += direction * arcs[i] / 2
centre(text: characters[i],
context: context,
radius: r,
angle: thetaI,
colour: c,
font: font,
slantAngle: thetaI + slantCorrection)
thetaI += direction * arcs[i] / 2
}
}
func chordToArc(_ chord: CGFloat, radius: CGFloat) -> CGFloat {
return 2 * asin(chord / (2 * radius))
}
func centre(text str: String,
context: CGContext,
radius r: CGFloat,
angle theta: CGFloat,
colour c: NSColor,
font: NSFont,
slantAngle: CGFloat) {
let attributes = [NSAttributedString.Key.foregroundColor: c, NSAttributedString.Key.font: font]
context.saveGState()
context.translateBy(x: r * cos(theta), y: -(r * sin(theta)))
context.rotate(by: -slantAngle)
let offset = str.size(withAttributes: attributes)
context.translateBy (x: -offset.width / 2, y: -offset.height / 2)
str.draw(at: CGPoint(x: 0, y: 0), withAttributes: attributes)
context.restoreGState()
}
class CustomView: NSView {
let textOnCurve = TextOnCurve()
override init(frame: NSRect) {
super.init(frame: frame)
wantsLayer = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func updateLayer() {
let textOnCurveLayer = CAShapeLayer()
textOnCurveLayer.frame = self.frame
textOnCurveLayer.delegate = textOnCurve
textOnCurveLayer.setNeedsDisplay()
layer?.addSublayer(textOnCurveLayer)
}
}
class TextOnCurve: NSObject, CALayerDelegate {
func draw(_ layer: CALayer, in ctx: CGContext) {
ctx.setFillColor(.white)
ctx.move(to: CGPoint(x: 100, y: 100))
ctx.addLine(to: CGPoint(x: 150, y: 100))
ctx.addLine(to: CGPoint(x: 150, y: 150))
ctx.addLine(to: CGPoint(x: 100, y: 150))
ctx.closePath()
ctx.drawPath(using: .fill)
ctx.translateBy(x: 200.0, y: 200.0)
centreArcPerpendicular(text: "Anticlockwise",
context: ctx,
radius: 100,
angle: CGFloat(-.pi/2.0),
colour: .red,
font: NSFont.systemFont(ofSize: 16),
clockwise: false)
centre(text: "Hello flat world",
context: ctx,
radius: 0,
angle: 0 ,
colour: .yellow,
font: NSFont.systemFont(ofSize: 16),
slantAngle: .pi / 4)
}
}
let containerView = CustomView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
PlaygroundPage.current.liveView = containerView
框已绘制,但文本未绘制。
如果我不使用图层,那么我可以通过调用标准draw:
方法中的方法来绘制文本。所以代码应该可以工作,但是,关于层的使用会阻止它。
解决方案
推荐阅读
- r - 当我在 R Shiny 中选择数据框“emp.data B”时,如何将标题/标签呈现为“摘要”?
- hyperledger-fabric - 如何在超级账本结构网络中实现提交节点?
- python - Django_q 调度程序问题
- javascript - 如何将 API 响应时间从 Fetch 函数传递到另一个异步函数?
- php - PHP 中的 HMAC sha256 不以十六进制和破折号 (-) 返回输出
- c++ - 统一缓冲区对象中的数组问题
- flutter - 搜索时 Youtube 视频一直在开始
- vb.net - 变量未声明。由于其保护级别,它可能无法访问
- security - AzSK 扫描询问用户在管道中的选择
- wordpress - Wordpress Rest api查询空对象元