使用CASpringAnimation对CAShapeLayer路径进行动画处理

时间:2018-12-11 17:14:13

标签: ios swift cashapelayer

enter image description here

我有一个自定义UIView,在其中添加了CAShapeLayer作为视图层的直接子层:

private let arcShapeLayer = CAShapeLayer()

CAShapeLayer具有在awakeFromNib中声明的以下属性(边框是为了使动画更容易可视化):

arcShapeLayer.lineWidth = 2.0
arcShapeLayer.strokeColor = UIColor.black.cgColor
arcShapeLayer.fillColor = UIColor.lightGray.cgColor
arcShapeLayer.masksToBounds = false
layer.masksToBounds = false
layer.addSublayer(arcShapeLayer)

我在arcShapeLayer中声明layoutSubviews的帧:

arcShapeLayer.frame = layer.bounds

然后,我具有以下函数,我通过传递一定百分比(来自ViewController)以在拖动后达到圆弧效果。简而言之,我在层的底部添加了一个quadCurve

func configureArcPath(curvePercentage: CGFloat) -> CGPath {

    let path = UIBezierPath()
    path.move(to: CGPoint.zero)
    path.addLine(to:
        CGPoint(
            x: arcShapeLayer.bounds.minX,
            y: arcShapeLayer.bounds.maxY
        )
    )

    path.addQuadCurve(
        to:
        CGPoint(
            x: arcShapeLayer.bounds.maxX,
            y: arcShapeLayer.bounds.maxY
        ),
        controlPoint:
        CGPoint(
            x: arcShapeLayer.bounds.midX,
            y: arcShapeLayer.bounds.maxY + arcShapeLayer.bounds.maxY * (curvePercentage * 0.4)
        )
    )

    path.addLine(to:
        CGPoint(
            x: arcShapeLayer.bounds.maxX,
            y: arcShapeLayer.bounds.minY
        )
    )
    path.close()

    return path.cgPath

}

然后,我尝试使用以下代码为圆弧赋予弹簧效果动画:

func animateArcPath() {

    let springAnimation = CASpringAnimation(keyPath: "path")
    springAnimation.initialVelocity = 10
    springAnimation.mass = 10
    springAnimation.duration = springAnimation.settlingDuration
    springAnimation.fromValue = arcShapeLayer.path
    springAnimation.toValue = configureArcPath(curvePercentage: 0.0)
    springAnimation.fillMode = .both
    arcShapeLayer.add(springAnimation, forKey: nil)

    arcShapeLayer.path = configureArcPath(curvePercentage: 0.0)

}

正如您在视频中看到的那样,问题是电弧永远不会过冲。尽管它会在其原始位置和静止位置之间振荡,但从未达到弹簧效果。

我在这里想念什么?

1 个答案:

答案 0 :(得分:2)

我玩了这个,我可以报告您绝对正确。它与钳位为零无关。可见的动画在两个极端都固定。

比方说,您提供了一个较大的质量值,以便使超调量超出凸弓返回原处的初始位置回到起点。然后我们看到的是,动画将两者都固定在原始位置,而则最小化了您要设置动画的位置。当弹簧在它们之间摆动时,我们看到动画在一个极端和另一个极端之间发生,但是当达到最大值或最小值时,它只是夹紧在那里,直到它有时间充分摆动并返回。

我必须得出结论,CAShapeLayer @IBAction func animateArcPath() { self.animate(to:-1, in:0.5, from:arcShapeLayer.path!) } func animate(to arc:CGFloat, in time:Double, from current:CGPath) { let goal = configureArcPath(curvePercentage: arc) let anim = CABasicAnimation(keyPath: "path") anim.duration = time anim.fromValue = current anim.toValue = goal anim.delegate = self anim.setValue(arc, forKey: "arc") anim.setValue(time, forKey: "time") anim.setValue(goal, forKey: "pathh") arcShapeLayer.add(anim, forKey: nil) } func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { if let arc = anim.value(forKey:"arc") as? CGFloat, let time = anim.value(forKey:"time") as? Double, let p = anim.value(forKey:"pathh") { if time < 0.05 { return } self.animate(to:arc*(-0.5), in:time*0.5, from:p as! CGPath) } } 不喜欢弹出动画。 CAShapeLayer path spring animation not 'overshooting'

提出了同样的观点

通过链接普通的基本动画,我能够模拟出您的外观:

enter image description here

这是我使用的代码(基于您自己的代码):

adb push * /sdcard/Music