平滑地加速正在运行的旋转动画

Posted

技术标签:

【中文标题】平滑地加速正在运行的旋转动画【英文标题】:Smoothly speed up an running rotation animation 【发布时间】:2017-08-26 04:59:22 【问题描述】:

我使用这段代码来旋转任何视图:

func rotateAnimation(theView: UIView, duration: CFTimeInterval = 20.0, repeatCount: Float = 200, toValue: CGFloat = CGFloat(.pi * 2.0)) 
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
    rotateAnimation.fromValue = 0.0
    rotateAnimation.toValue = toValue
    rotateAnimation.duration = duration
    rotateAnimation.repeatCount = repeatCount
    theView.layer.add(rotateAnimation, forKey: nil)

我想知道如何加快当前正在运行的动画。例如,如果 UIView 正在使用上面的代码旋转,我怎样才能通过漂亮的转换使速度提高两倍?

所以:调用 rotateAnimation:以正常速度旋转 -> 调用 ?function? -> UIView 将平稳地以更快的速度旋转到所需的速度 -> UIView 将继续以所需的速度。

感谢您的帮助。

【问题讨论】:

更改持续时间有帮助吗? @3stud1ant3 不,它改变了速度,但几秒钟后动画又恢复到原来的速度。 在与更改持续时间相同的注意事项上,您是否尝试过使用条件行指定动画最终位置的 while 循环? 【参考方案1】:

请尝试以下代码

       let timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true)  (timer) in
            self.viewToMove.layer.timeOffset = self.viewToMove.layer.convertTime(CACurrentMediaTime(), from: nil)
            self.viewToMove.layer.beginTime = CACurrentMediaTime()
            self.viewToMove.layer.speed += 0.5

        
        timer.fire()

它会非常流畅地提高动画速度

【讨论】:

【参考方案2】:

在第二个动画中试试这个

你可以设置更小的持续时间来提高速度

func rotateAnimation(theView: UIView, duration: CFTimeInterval = 0.4, repeatCount: Float = 200, toValue: CGFloat = CGFloat(.pi * 2.0)) 
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
    rotateAnimation.fromValue = 0.0
    rotateAnimation.toValue = toValue
    rotateAnimation.duration = duration
    rotateAnimation.repeatCount = repeatCount

并设置 shouldRasterize = true 以获得更好的性能

    theView.layer.rasterizationScale = UIScreen.main.scale
    theView.layer.shouldRasterize = true

对两个动画使用相同的键

    theView.layer.add(rotateAnimation, forKey: "animation")

【讨论】:

【参考方案3】:

将重复计数设置为 1,并在每个动画停止后重新添加动画。我不确定这是否会导致您的场景出现性能问题,因为我使用非常基本的方形视图对其进行了测试。

通过添加CAMediaTimingFunction 参数,您可以控制是否使用kCAMediaTimingFunctionLinear——用于那些正常的动画循环,或者使用自定义循环,例如kCAMediaTimingFunctionEaseIn——用于关键动画帧以显示平滑过渡。

// your function to start the acceleration
@IBAction func buttonTapped(_ sender: UIButton) 
    accel = true
    speed = 2.0
    timeOffset = self.rect.layer.convertTime(CACurrentMediaTime(), from: nil)
    timeOffset = timeOffset - lastStart
    // memorize the timeoffset, new speed (2x) and a boolean flag
    self.rect.layer.removeAllAnimations()


// delegate - memorize the CFTimeInterval
func animationDidStart(_ anim: CAAnimation) 
    lastStart = self.rect.layer.convertTime(CACurrentMediaTime(), from: nil)


// delegate - start a new loop of animation each time it's stopped
func animationDidStop(_ anim: CAAnimation, finished flag: Bool) 
    if accel 
        accel = false
        let opt = CAMediaTimingFunction(controlPoints: 0.5, 0.2, 0.9, 0.7)
        rotateAnimation(theView: rect, speed: speed, fromValue: CGFloat(.pi * 2.0 * Float(timeOffset) / 10.0), toValue: CGFloat(.pi * 2.0 * Float(timeOffset) / 10.0 + .pi * 2.0), option: opt)
     else 
        rotateAnimation(theView: rect, speed: speed, fromValue: CGFloat(.pi * 2.0 * Float(timeOffset) / 10.0), toValue: CGFloat(.pi * 2.0 * Float(timeOffset) / 10.0 + .pi * 2.0))
        // note that timeOffset is initialize to be 0.
    

这里你想要一个自定义的CAMediaTimingFunction,从0.5的斜率开始逐渐增加到1.0,这里我没有优化贝塞尔曲线,你可以做你自己想要的曲线。

最后稍微调整一下你的动画功能:

func rotateAnimation(theView: UIView, speed: Float, duration: CFTimeInterval = 10.0, fromValue: CGFloat = CGFloat(0.0), toValue: CGFloat = CGFloat(.pi * 2.0), option: CAMediaTimingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)) 
    let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
    rotateAnimation.fromValue = fromValue
    rotateAnimation.toValue = toValue
    rotateAnimation.duration = duration
    rotateAnimation.speed = speed
    rotateAnimation.repeatCount = 1
    rotateAnimation.delegate = self
    rotateAnimation.timingFunction = option
    theView.layer.add(rotateAnimation, forKey: nil)

【讨论】:

以上是关于平滑地加速正在运行的旋转动画的主要内容,如果未能解决你的问题,请参考以下文章

平滑的 CSS 过渡动画旋转

在未知关键帧上平滑停止 CSS 旋转动画

动画旋转UIImageView

在视图控制器之间切换时,图像旋转动画会加速吗

Blender 导出 three.js 动画 - 骨骼奇怪地旋转

Android缩放和旋转动画不流畅,跳跃