Create a continuously rotating square on the screen using animateKeyframesWithDuration

妖精的绣舞 提交于 2019-12-05 03:28:16

That's really odd... UIView.animateKeyframesWithDuration isn't working as I would expect it to with UIViewKeyframeAnimationOptions.CalculationModeLinear|UIViewKeyframeAnimationOpti‌​ons.Repeat passed in with options.

If you use the non-block method of creating a keyframe animation (see below) the rotation repeats as expected.

If I find out why the block-based option isn't working I'll try and remember to update answer here too!

override func viewDidLoad() {
    super.viewDidLoad()


    let square = UIView()
    square.frame = CGRect(x: 55, y: 300, width: 40, height: 40)
    square.backgroundColor = UIColor.redColor()
    self.view.addSubview(square)

    let fullRotation = CGFloat(M_PI * 2)

    let animation = CAKeyframeAnimation()
    animation.keyPath = "transform.rotation.z"
    animation.duration = 2
    animation.removedOnCompletion = false
    animation.fillMode = kCAFillModeForwards
    animation.repeatCount = Float.infinity
    animation.values = [fullRotation/4, fullRotation/2, fullRotation*3/4, fullRotation]

    square.layer.addAnimation(animation, forKey: "rotate")

}
Alan Zhang

I faced same problem before, this is how I make it work:

Swift 2

let raw = UIViewKeyframeAnimationOptions.Repeat.rawValue | UIViewAnimationOptions.CurveLinear.rawValue
let options = UIViewKeyframeAnimationOptions(rawValue: raw)

Swift 3,4,5

let raw = UIView.KeyframeAnimationOptions.repeat.rawValue | UIView.AnimationOptions.curveLinear.rawValue
let options = UIView.KeyframeAnimationOptions(rawValue: raw)

I figured this problem out just before gave it up. I don't think there is doc about it, but it just work.

Add UIViewKeyframeAnimationOptionCalculationModeLinear do your keyframe options. The default behavior for UIView animations is to "ease in/out" of the animation. i.e., start slow, go up to speed, then slow down again just near the end.

Anton

AFAIU, this is happening because the default animation curve is UIViewAnimationOption.CurveEaseInOut.

Unfortunately, UIViewKeyframeAnimationOptions doesn't have options for changing the curve, but you can add them manually!

Use this extension:

Swift 2

extension UIViewKeyframeAnimationOptions {
    static var CurveEaseInOut: UIViewKeyframeAnimationOptions { return UIViewKeyframeAnimationOptions(rawValue: UIViewAnimationOptions.CurveEaseInOut.rawValue) }
    static var CurveEaseIn: UIViewKeyframeAnimationOptions { return UIViewKeyframeAnimationOptions(rawValue: UIViewAnimationOptions.CurveEaseIn.rawValue) }
    static var CurveEaseOut: UIViewKeyframeAnimationOptions { return UIViewKeyframeAnimationOptions(rawValue: UIViewAnimationOptions.CurveEaseOut.rawValue) }
    static var CurveLinear: UIViewKeyframeAnimationOptions { return UIViewKeyframeAnimationOptions(rawValue: UIViewAnimationOptions.CurveLinear.rawValue) }
}

Swift 3, 4, 5

extension UIView.KeyframeAnimationOptions {
    static var curveEaseInOut: UIView.KeyframeAnimationOptions { return UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.curveEaseInOut.rawValue) }
    static var curveEaseIn: UIView.KeyframeAnimationOptions { return UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.curveEaseIn.rawValue) }
    static var curveEaseOut: UIView.KeyframeAnimationOptions { return UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.curveEaseOut.rawValue) }
    static var curveLinear: UIView.KeyframeAnimationOptions { return UIView.KeyframeAnimationOptions(rawValue: UIView.AnimationOptions.curveLinear.rawValue) }
}

Now you can use curve options in UIView.animateKeyframesWithDuration method

Swift 2

let keyframeOptions: UIViewKeyframeAnimationOptions = [.Repeat, .CurveLinear]
UIView.animateKeyframesWithDuration(duration, delay: delay, options: keyframeOptions, animations: {
    // add key frames here
}, completion: nil)

Swift 3, 4, 5

let keyframeOptions: UIView.KeyframeAnimationOptions = [.repeat, .curveLinear]
UIView.animateKeyframes(withDuration: duration, delay: delay, options: keyframeOptions, animations: {
    // add key frames here
}, completion: nil)
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!