我试图通过设置背衬层的变换动画,在支持图层的NSView上运行缩放动画。我遇到的问题是,动画放大到左下角而不是视图的中心。我发现这是因为NSView将其支持层的锚点设置为(0,0),即使我将其更改为其他值也是如此。这篇post讨论了类似的问题。
我知道要解决这个问题,我可以将视图作为图层托管视图。但是,我想使用自动布局,这就是为什么这不是一个真正的选择。
有没有人知道绕过这种行为的另一种方法,并将视图的背景层的锚点保持在(0.5,0.5)?我在上面链接的帖子中摘录了苹果的文档,讨论了NSView封面方法。什么样的覆盖方法可以用于锚点?
非常感谢!
答案 0 :(得分:0)
诀窍是覆盖支持层并传递选择的锚点(例如,能够从左上角缩放)。这是我使用的:
extension CGPoint {
static let topLeftAnchor: Self = .init(x: 0.0, y: 1.0)
static let bottomLeftAnchor: Self = .init(x: 0.0, y: 0.0)
static let topRightAnchor: Self = .init(x: 1.0, y: 1.0)
static let bottomRightAnchor: Self = .init(x: 1.0, y: 0.0)
static let centerAnchor: Self = .init(x: 0.5, y: 0.5)
}
class AnchoredLayer: CALayer {
public var customAnchorPoint = CGPoint.topLeftAnchor
override var anchorPoint: CGPoint {
get { customAnchorPoint }
set { super.anchorPoint = customAnchorPoint }
}
}
class AnchoredView: NSView {
required convenience init(anchoredTo point: CGPoint) {
self.init(frame: .zero)
self.wantsLayer = true
self.anchorPoint = point
}
public override func makeBackingLayer() -> CALayer {
let roundedLayer = AnchoredLayer()
return roundedLayer
}
public var anchorPoint: CGPoint {
get { (layer as! AnchoredLayer).customAnchorPoint }
set { (layer as! AnchoredLayer).customAnchorPoint = newValue }
}
}
然后照常使用AnchoredView
:
let myView = AnchoredView(anchoredTo: .topLeftAnchor)
// Create the scale animation
let transformScaleXyAnimation = CASpringAnimation()
transformScaleXyAnimation.fillMode = .forwards
transformScaleXyAnimation.keyPath = "transform.scale.xy"
transformScaleXyAnimation.toValue = 1
transformScaleXyAnimation.fromValue = 0.8
transformScaleXyAnimation.stiffness = 300
transformScaleXyAnimation.damping = 55
transformScaleXyAnimation.mass = 0.8
transformScaleXyAnimation.initialVelocity = 4
transformScaleXyAnimation.duration = transformScaleXyAnimation.settlingDuration
myView.layer?.add(transformScaleXyAnimation, forKey: "transformScaleXyAnimation")
...