6

I develop an app which requires a wheel to be rotated around z axis with increasing or decreasing the speed of the wheel steadily over time. I use CABasicAnimation & my code is as follows. While i change the speed property of the layer at particular interval, it causes "Jerk" effect to the wheel.

/****/

CABasicAnimation* animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
animation.toValue = [NSNumber numberWithFloat:-2*M_PI];
animation.duration = 4.0f;
animation.repeatCount = INFINITY;
[animation setValue:@"left" forKey:@"side"];
[animation setDelegate:self];
animation.removedOnCompletion=NO;
animation.fillMode = kCAFillModeForwards;
animation.cumulative = YES;

imageLeft.layer.beginTime = CACurrentMediaTime();
/************/

In a timer I vary the speed of the CALayer of the imageview as follows where dPlayedPercentage is a variable.

imageLeft.layer.speed=1.0+dPlayedPercentage;

[imageLeft.layer addAnimation:animation forKey:@"SpinAnimation"];

I think it is due to the position resets while changing the speed property of CALayer. What should i do to rectify this. Or any other way to do this animation?

Augus
  • 221
  • 2
  • 9
  • Adding the following code has rectified the jerk in the animation. imageLeft.layer.timeOffset = [imageLeft.layer convertTime:CACurrentMediaTime() fromLayer:nil]; imageLeft.layer.beginTime = CACurrentMediaTime(); imageLeft.layer.speed=1.0+dPlayedPercentage; – Augus Jul 20 '13 at 12:08

2 Answers2

15

Adding the following code has rectified the jerk in the animation.

imageLeft.layer.timeOffset = [imageLeft.layer convertTime:CACurrentMediaTime() fromLayer:nil]; 
imageLeft.layer.beginTime = CACurrentMediaTime(); 
imageLeft.layer.speed=1.0+dPlayedPercentage;
Flexo
  • 87,323
  • 22
  • 191
  • 272
Augus
  • 221
  • 2
  • 9
  • 1
    +1 I had pretty much the same problem, of having a layer that was animating, and I wanted to change the speed mid-animation without restarting the animation. This worked for me, thanks. – Siegfoult Jun 26 '14 at 21:15
  • 1
    @Augus @Siegfoult I am having similar issue, can you show me how you manage `dPlayedPercentage ` value. – Milan Gupta Dec 20 '16 at 11:33
1

For more dynamic speed change, I has some issue with the previous answer (layer not drawing at all) since the timeOffset needed to be calculated with the new speed in mind.

(source https://coveller.com/2016/05/core_animation_timing)

The base formula for the timeOffset is:
timeOffset = CACurrentMediaTime() - ((convertTime - beginTime) x speed)

In code:

theLayer.speed = newSpeed
    
let mediaTime = CACurrentMediaTime()
    
let converedTime = theLayer.convertTime(mediaTime, to: nil)
    
theLayer.beginTime = mediaTime

let offset = mediaTime - ((converedTime - theLayer.beginTime) * Double(newSpeed))

theLayer.timeOffset = offset
bauerMusic
  • 5,470
  • 5
  • 38
  • 53