我有一个自定义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)
}
正如您在视频中看到的那样,问题是电弧永远不会过冲。尽管它会在其原始位置和静止位置之间振荡,但从未达到弹簧效果。
我在这里想念什么?
答案 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'
通过链接普通的基本动画,我能够模拟出您的外观:
这是我使用的代码(基于您自己的代码):
adb push * /sdcard/Music