CAKeyFrameAnimation not Linear for values greater than PI

我的未来我决定 提交于 2019-12-23 09:17:08

问题


I am having some trouble to understand why an animation isn't working like expected. What I am doing is this:

  1. 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
    
  2. Add this path to a CAShapeLayer

    circlePathLayer.frame = bounds
    circlePathLayer.path = self.path.cgPath
    circlePathLayer.strokeStart = 0
    circlePathLayer.strokeEnd = 1
    
  3. Animate the strokeEnd property with a 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
    
  4. Animate the position property of my label with a CAKeyFrameAnimation

    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
    
  5. Add my animations to layer and label

    self.circlePathLayer.add(animation, forKey: nil)
    self.scoreLabel.layer.add(animationScore, forKey: nil)
    

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 :

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


回答1:


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:

  • The shape layer's strokeEnd, like your animation.

  • 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.)

This is the entire animation code:

    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)


来源:https://stackoverflow.com/questions/42158323/cakeyframeanimation-not-linear-for-values-greater-than-pi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!