Search code examples
iosgeometrylayerimage-rotationcabasicanimation

CABasicAnimation - Change animation start value during pause


In order to rotate circle in 360 I use CABasicAnimation, in this way :

func startRotate(from : Double) {
    let rotation : CABasicAnimation = CABasicAnimation(keyPath: "transform.rotation.z")
    rotation.fromValue = from
    rotation.toValue = NSNumber(value: M_PI * 2 - from)
    rotation.duration = 10
    rotation.isCumulative = true
    rotation.repeatCount = 1
    self.cdImage.layer.add(rotation, forKey: "rotationAnimation")

}

At the first time the cdImage (view) start from value 0.

When the animation arrived to the middle (after 5 sec) I want to stop the animation and set a transform for the cdImage view, for example return the view 20 degree back and resume it from the new position.

by this way: 1. I call to stopRotate function

func stopRotate(from : Double) {
    self.cdImage.layer.removeAnimation(forKey: "rotationAnimation")   
 }
  1. I set a new transform

    self.cdImage.transform = CGAffineTransform(rotationAngle: imageAngle *  CGFloat(M_PI) / 180);
    
  2. call to startRotate with a new value

    startRotate(imageAngle * CGFloat(M_PI) / 180)

I suppose that animation will start from the new position and rotate again the view in 360 degree, but actually the animation start the circle from 0 degree, how I can resume the new animation from the new position?


Solution

  • If you want to pick up from where you left off, when you stop the animation, you want to:

    • capture how much it has rotated (see https://stackoverflow.com/a/9712319/1271826);
    • determine the in-flight value by examining the presentation layer;
    • set the transform of the layer accordingly (so that it stays there when you remove the animation); and
    • remove the animation

    Thus:

    var angle: CGFloat?
    
    func stopRotate() {
        let transform = cdImage.layer.presentation()!.transform
        angle = atan2(transform.m12, transform.m11);
        cdImage.layer.transform = transform
        cdImage.layer.removeAnimation(forKey: "rotationAnimation")
    }
    

    You can then start the animation from that angle when you restart it.