对于大于PI的值,CAKeyFrameAnimation不是线性的 [英] CAKeyFrameAnimation not Linear for values greater than PI

查看:133
本文介绍了对于大于PI的值,CAKeyFrameAnimation不是线性的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解为什么动画无法正常工作。
我正在做什么:

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


  1. 创建 UIBezierPath 用弧线沿该路径移动Label并设置路径笔画的动画。

  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


  • 将此路径添加到 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

    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屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆