平滑地加快运行旋转动画的速度



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

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 使用上面的代码旋转,我怎样才能通过漂亮的转换使速度快两倍?

所以:调用旋转动画:以正常速度旋转 ->调用 ?函数?-> UIView 将平稳地旋转得更快到所需的速度 -> UIView 将继续以所需的速度旋转。

感谢您的任何帮助。

请尝试以下代码

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

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

尝试第二个动画

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

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

并设置应该栅格化 = true 以获得更好的性能

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

对两个动画使用相同的关键帧

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

将重复计数设置为 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)
}

最新更新