平滑地加速正在运行的旋转动画
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)
【讨论】:
以上是关于平滑地加速正在运行的旋转动画的主要内容,如果未能解决你的问题,请参考以下文章