对于大于PI的值,CAKeyFrameAnimation不是线性的 [英] CAKeyFrameAnimation not Linear for values greater than PI
问题描述
我很难理解为什么动画无法正常工作。
我正在做什么:
I am having some trouble to understand why an animation isn't working like expected. What I am doing is this:
-
创建
UIBezierPath
用弧线沿该路径移动Label并设置路径笔画的动画。
Create a
UIBezierPath
with an arc to move a Label along this path and animate the paths stroke.
//Start Point is -.pi /2 to let the Arc start at the top.
//self.progress = Value between 0.0 and 1.0
let path : UIBezierPath = UIBezierPath.init(arcCenter: CGPoint.init(x: self.bounds.width * 0.5, y: self.bounds.height * 0.5),
radius: self.bounds.width * 0.5, startAngle: -.pi / 2, endAngle: (2 * self.progress * .pi) - (.pi / 2), clockwise: true)
return path
将此路径添加到 CAShapeLayer
circlePathLayer.frame = bounds
circlePathLayer.path = self.path.cgPath
circlePathLayer.strokeStart = 0
circlePathLayer.strokeEnd = 1
使用 CABasicAnimation
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.repeatCount = HUGE
animation.fromValue = 0.0
animation.toValue = 1.0
animation.duration = self.animationDuration
animation.isRemovedOnCompletion = false
animation.fillMode = kCAFillModeBoth
使用 CAKeyFrameAnimation $ c对标签的位置属性进行动画处理$ c>
let animationScore = CAKeyframeAnimation(keyPath: "position")
//some things I tried to fix
//animationScore.timingFunctions = [CAMediaTimingFunction(controlPoints: 0.250, 0.250, 0.750, 0.750)]
//animationScore.timingFunction = CAMediaTimingFunction.init(name: kCAMediaTimingFunctionLinear)
animationScore.path = self.path.cgPath
animationScore.duration = self.animationDuration
animationScore.isRemovedOnCompletion = false
animationScore.fillMode = kCAFillModeBoth
animationScore.repeatCount = HUGE
将我的动画添加到图层并标记
Add my animations to layer and label
self.circlePathLayer.add(animation, forKey: nil)
self.scoreLabel.layer.add(animationScore, forKey: nil)
我的问题:对于ProgressValues越大t 0.75以上我的标签没有以线性速度移动。值大于0.75表示我的弧大于PI。
对于小于0.75的值,我的动画可以正常工作,并且标签和描边具有相同的速度,并且彼此重叠。
My Problem: For ProgressValues greater than 0.75 my label is not moving in linear speed. Values greater than 0.75 mean that my arc is greater than PI. For values less than 0.75 my animation works fine and label and strokeend have the same speed and are on top of each other.
GIF:
GIF :
请忽略此标签中标签中的100%,我的进度值为0.76。
Please ignore the 100% in the Label in this gif my progress was at a value of 0.76.
您看到我的标签在我圈子的四分之三后变慢了。
You see my Label slows down after three quarters of my circle.
我希望有人能帮助我。
非常感谢
I hope someone can help me. Many thanks
推荐答案
关键帧动画引入了不必要的复杂性。只需以与形状图层的笔触动画相同的持续时间在中心旋转标签即可:
The keyframe animation introduces an unnecessary complication. Simply rotate the label around the center with the same duration as the shape layer's stroke animation:
(很抱歉,我的动画从底部开始,而不是从顶部开始,但是当我编写代码时,我没有看您的问题,现在我懒得更改它! )
(I apologize that my animation starts at the bottom, not the top, but I wasn't looking at your question when I wrote the code and now I'm too lazy to change it!)
那么,这是怎么做的呢?这是三个动画,都具有相同的持续时间:
So, how is that done? It's three animations, all with the same duration:
-
形状层的
strokeEnd
,就像动画一样。
在圆心处延伸的手臂,标签的一端是子层(因此标签出现在圆的半径处)。手臂执行旋转变换动画。
An "arm" running thru the center of the circle, with the label as a sublayer at one end (so that the label appears at the radius of the circle). The arm does a rotation transform animation.
标签沿相反方向执行旋转变换动画。如果没有,它将随其上层一起旋转。 (想想摩天轮是如何工作的;您的椅子位于手臂的末端,但相对于地球仍保持直立。)
The label does a rotation transform animation in the opposite direction. If it didn't, it would rotate along with its superlayer. (Think of how a Ferris wheel works; your chair is on the end of the arm, but it remains upright with respect to the earth.)
这是整个动画代码:
let anim = CABasicAnimation(keyPath: "transform.rotation.z")
anim.fromValue = 0
anim.toValue = 5
anim.duration = 10
self.arm.layer.add(anim, forKey:nil)
let anim2 = CABasicAnimation(keyPath: "transform.rotation.z")
anim2.fromValue = 0
anim2.toValue = -5
anim2.duration = 10
self.lab.layer.add(anim2, forKey:nil)
let anim3 = CABasicAnimation(keyPath: "strokeEnd")
anim3.fromValue = 0
anim3.toValue = 1
anim3.duration = 10
self.shape.add(anim3, forKey:nil)
这篇关于对于大于PI的值,CAKeyFrameAnimation不是线性的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!