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

时间:2017-08-26 04:59:23

标签: ios swift animation uiview

我使用此代码旋转任何视图:

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 :以正常速度旋转 - > 电话?功能? - > UIView将顺利地更快地旋转到所需的速度 - > UIView将以所需的速度继续旋转。

感谢您的帮助。

3 个答案:

答案 0 :(得分:2)

请尝试以下代码

       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()

它会非常顺利地提高动画速度

答案 1 :(得分:0)

尝试第二个动画

您可以设置较小的持续时间以提高速度

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")
}

答案 2 :(得分:0)

将repeatcount设置为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)
}