【发布时间】:2018-06-10 20:19:29
【问题描述】:
我目前正在尝试实现一些自定义 NSView,它们将通过 macOS 应用程序中的某些事件进行动画处理。控件与您在 AudioUnit 插件中找到的滑块线相同。
动画问题已在this question回答。
我不确定的是如何更改视图的 CALayer 位置和锚点以进行旋转并更新其帧以进行鼠标事件。
作为一个基本示例,我希望通过创建一个 NSView 并设置它的背景颜色来绘制一个正方形。然后,我想在 mouseDown 事件上为视图的旋转设置动画,就像上一个链接一样。
通过以下设置,视图被移动到窗口的中心,它的锚点被改变,以便视图围绕它而不是围绕window.contentView! 的原点旋转。但是,移动view.layer.position 和设置view.layer!.anchorPoint = CGPoint(x: 0.5,y: 0.5) 不会同时移动将检测事件的框架。
@IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification)
{
let view = customView(frame: NSRect(x: 0, y: 0, width: 50, height: 50))
window.contentView!.wantsLayer = true
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.blue.cgColor
window.contentView?.addSubview(view)
let containerFrame = window.contentView!.frame
let center = CGPoint(x: containerFrame.midX, y: containerFrame.midY)
view.layer?.position = center
view.layer?.anchorPoint = CGPoint(x: 0.5,y: 0.5)
}
在这种情况下,customView 只是一个 NSView,其中包含在 mouseDown 上执行的上一个链接的旋转动画
override func mouseDown(with event: NSEvent)
{
let timeToRotate = 1
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.fromValue = 0.0
rotateAnimation.toValue = angle
rotateAnimation.duration = timeToRotate
rotateAnimation.repeatCount = .infinity
self.layer?.add(rotateAnimation, forKey: nil)
}
通过设置view.frame = view.layer.frame 移动框架会导致视图围绕其中一个角旋转。所以,我改变了view.setFrameOrigin()
@IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(_ aNotification: Notification)
{
let view = customView(frame: NSRect(x: 0, y: 0, width: 50, height: 50))
window.contentView!.wantsLayer = true
view.wantsLayer = true
view.layer?.backgroundColor = NSColor.blue.cgColor
window.contentView?.addSubview(view)
let containerFrame = window.contentView!.frame
let center = CGPoint(x: containerFrame.midX, y: containerFrame.midY)
let offsetFrameOrigin = CGPoint(x: center.x - view.bounds.width/2,
y: center.y - view.bounds.height/2)
view.setFrameOrigin(offsetFrameOrigin)
view.layer?.position = center
view.layer?.anchorPoint = CGPoint(x: 0.5,y: 0.5)
}
将 view.frame 原点设置为中心的偏移量可以实现我想要的,但我不禁觉得这有点“hacky”,而且我可能以错误的方式接近它。特别是因为对view.layer 或view.frame 的任何进一步更改都将导致动画不正确或在绘制之外检测到事件。
如何更改 NSView.layer 使其在设置 NSView.frame 的同时围绕其中心旋转,以便在正确的区域检测到鼠标事件?
另外,改变NSView.layer.anchorPoint 是设置它围绕其中心旋转的正确方法吗?
【问题讨论】:
-
你认为这与 Xcode 10 / Mojave 有什么关系吗?我已经完成了大约 10 个教程,终于在不弄乱锚点的情况下让图层旋转工作,只是发现和你一样,我的“事件区域”被翻译掉了......重置自己...