【问题标题】:NSView scale animation is not smoothNSView 缩放动画不流畅
【发布时间】:2023-08-02 08:11:02
【问题描述】:

我正在尝试缩放 56x56 的 NSView。动画应用 0.95 的比例和 0.75 的 alpha,自动反转并无限重复。我有动画工作,但是动画非常厚实(不流畅)。

如何使用CAAnimationGroupCABasicAnimation 平滑地为这些属性设置动画?

你可以在这个 gif 中看到厚实的动画

动画代码如下所示

private func transformWithScale(_ scale: CGFloat) -> CATransform3D {
    let bounds = squareView.bounds
    let scale = scale != 0 ? scale : CGFloat.leastNonzeroMagnitude
    let xPadding = 0.5*bounds.width
    let yPadding = 0.5*bounds.height
    let translate = CATransform3DMakeTranslation(xPadding, yPadding, 0.0)
    return scale == 1.0 ? translate : CATransform3DScale(translate, scale, scale, 1.0)
}

func startAnimation() {
    let layer = squareView.layer!
    layer.removeAllAnimations()
    layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)

    let scaleAnimation = CABasicAnimation(keyPath: "transform")
    scaleAnimation.fromValue = transformWithScale(1.0)
    scaleAnimation.toValue = transformWithScale(0.95)

    let alphaAnimation = CABasicAnimation(keyPath: "opacity")
    alphaAnimation.fromValue = 1.0
    alphaAnimation.toValue = 0.75

    let group = CAAnimationGroup()
    group.duration = 0.8
    group.autoreverses = true
    group.timingFunction = CAMediaTimingFunction(name: .easeIn)
    group.repeatCount = .infinity
    group.animations = [scaleAnimation, alphaAnimation]

    layer.add(group, forKey: "scaleAndAlpha")
}

【问题讨论】:

    标签: cocoa nsview cabasicanimation


    【解决方案1】:

    试试这个:

    let container = NSView(frame: NSRect(x: 0, y: 0, width: 300, height: 300))
    container.wantsLayer = true
    container.layer?.backgroundColor = NSColor.blue.cgColor
    
    let content = NSView(frame: NSRect(x: 0, y: 0, width: 150, height: 150))
    content.wantsLayer = true
    content.layer?.backgroundColor = NSColor.red.cgColor
    container.addSubview(content)
    
    let layer = content.layer!
    
    let scaleAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.transform))
    scaleAnimation.fromValue = CATransform3DScale(CATransform3DIdentity, 1, 1, 1)
    scaleAnimation.toValue = CATransform3DScale(CATransform3DIdentity, 0.85, 0.85, 1)
    
    let alphaAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.opacity))
    alphaAnimation.fromValue = 1.0
    alphaAnimation.toValue = 0.75
    
    let group = CAAnimationGroup()
    group.duration = 0.8
    group.autoreverses = true
    group.timingFunction = CAMediaTimingFunction(name: .easeOut)
    group.repeatCount = .infinity
    group.animations = [scaleAnimation, alphaAnimation]
    
    let center = CGPoint(x: container.bounds.midX, y: container.bounds.midY)
    layer.position = center
    layer.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    layer.add(group, forKey: nil)
    
    PlaygroundPage.current.liveView = container
    

    【讨论】: