我目前正在构建一个绘图应用程序,该应用程序应该利用 CALayer 层次结构来避免在不必要时重新绘制每个图层(例如,我想在单独的 CALayer 上渲染临时内容,例如选择内容,而不重新渲染实际绘图)。
我的问题是我找不到禁用 CALayer 隐式动画的方法。
在此示例代码中,我在鼠标位置渲染了一个+,当我移动光标时,我可以看到旧的+淡出
class LayerViewAppKit: NSView {
let myLayer = MyLayer()
var mousePos : CGPoint!
var trackingArea: NSTrackingArea?
override init(frame frameRect: NSRect) {
super.init(frame: frameRect)
self.layer = myLayer
wantsLayer = true
}
required init?(coder: NSCoder) {
super.init(coder: coder)
print("not implemented")
}
override func updateTrackingAreas() {
super.updateTrackingAreas()
if let trackingArea = trackingArea {
removeTrackingArea(trackingArea)
}
let options: NSTrackingArea.Options = [.activeAlways, .mouseMoved]
trackingArea = NSTrackingArea(rect: bounds, options: options, owner: self, userInfo: nil)
addTrackingArea(trackingArea!)
}
override func mouseMoved(with event: NSEvent) {
let mousePos = convert(event.locationInWindow, from: nil)
myLayer.drawLines(at: mousePos)
}
}
这是自定义层实现
class MyLayer : CALayer {
var pos : CGPoint?
override func draw(in ctx: CGContext) {
guard let pos = pos else {return}
ctx.setStrokeColor(.black)
let vline = NSBezierPath()
vline.move(to: .init(x: 0, y: pos.y))
vline.line(to: .init(x: bounds.width, y: pos.y))
vline.lineWidth = 2
let hline = NSBezierPath()
hline.move(to: .init(x: pos.x, y: 0))
hline.line(to: .init(x: pos.x, y: bounds.height))
hline.lineWidth = 2
ctx.addPath(vline.cgPath)
ctx.addPath(hline.cgPath)
ctx.strokePath()
}
func drawLines(at pos : CGPoint){
self.pos = pos
setNeedsDisplay()
}
}
如何从 CALayer 中删除各种动画?
我尝试将绘图代码放入以下内容中:
CATransaction.begin()
CATransaction.setDisableActions(true)
//drawing code
CATransaction.commit()
并且还在不同的地方尝试过
myLayer.removeAllAnimations()
但没有成功。
为了避免动画,您需要隐式告诉图层事务禁用所有动画,然后提交更改。
CATransaction.begin()
CATransaction.setDisableActions(true)
// Set your new values here
CATransaction.commit()