6

In my application i am using CABasicAnimation for animation. I want to change the speed of the animation dynamically so i have added one slider to change the speed. Following is my animation code. But i am not able to change the speed, when i change the value of speed nothing happens.

        CABasicAnimation * a = [CABasicAnimation animationWithKeyPath:@"position"];
    [a setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear]];

    CGPoint startPt = CGPointMake(self.view.bounds.size.width + displayLabel.bounds.size.width / 2,
                                  displayLabel.frame.origin.y);
    CGPoint endPt = CGPointMake(displayLabel.bounds.size.width / -2, displayLabel.frame.origin.y);

    [a setFromValue:[NSValue valueWithCGPoint:startPt]];
    [a setToValue:[NSValue valueWithCGPoint:endPt]];
    [a setAutoreverses:NO];
    [a setDuration:speeds];
    [a setRepeatCount:HUGE_VAL];
    [displayLabel.layer addAnimation:a forKey:@"rotationAnimation"];


    - (IBAction)speedSlider:(id)sender {

         speeds = slider.value;

   }
Prerna chavan
  • 3,179
  • 7
  • 35
  • 77
  • Possible duplicate of [Change duration (speed) on a running animation](https://stackoverflow.com/questions/21589483/change-duration-speed-on-a-running-animation) – Fattie Aug 21 '17 at 01:14
  • **Full solution for 2017** ... https://stackoverflow.com/a/45787919/294884, phew – Fattie Aug 21 '17 at 01:15

6 Answers6

6

I think the best way to change speed is change your layer's time system

displayLabel.layer.timeOffset =
     [displayLabel.layer convertTime:CACurrentMediaTime() fromLayer:nil]; 
displayLabel.layer.beginTime = CACurrentMediaTime(); 
displayLabel.layer.speed= slider.value;

You can see this for advance. https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreAnimation_guide/AdvancedAnimationTricks/AdvancedAnimationTricks.html#//apple_ref/doc/uid/TP40004514-CH8-SW2

Fattie
  • 27,874
  • 70
  • 431
  • 719
Yu-Lin Wang
  • 131
  • 2
  • 5
  • @Fattie - probably you're looking for something different. This is the exact and precise answer for the problem. It works for me beautifully. – Les Nie Dec 28 '17 at 15:11
  • I do understand what you mean @LesNie - and yes it would provide a solution in some situations. However, it changes the time scale for the whole layer. Needing to change properties of a running animation is a common problem (and annoyingly difficult in iOS). I did click "+1" on your answer :) Happy new year! – Fattie Dec 28 '17 at 19:40
2

EDIT: It looks like you will have a further problem, though: it doesn't look like you can change values like that on a running animation. You will have to remove the current animation and add a new one with the altered value. This may need a bit of care to prevent a jarring effect when you add the new animation.

From the thread above, you might be able to do this by not repeating the animation, but by using a delegate (see here) to keep re-adding the animation, and setting the new speed for the next animation cycle instead.

Original post:

You are changing the value that you had originally passed in to the animation. This isn't going to affect the running animation. You'll need to get a reference to that, and change the duration property of the animation object. Something like this in your action method:

CABasicAnimation *a = [displayLabel.layer animationForKey:@"rotationAnimation"];
a.duration = slider.value;
mattsson
  • 1,329
  • 1
  • 14
  • 30
jrturton
  • 118,105
  • 32
  • 252
  • 268
  • I've looked into it a bit more and you can't change the value of a running animation. See my edit – jrturton Jun 26 '12 at 12:31
  • here's how you make a **restartable animation** these days in iOS .. https://stackoverflow.com/a/45787919/294884 – Fattie Aug 21 '17 at 01:15
1

I think jrturton is correct that you can't change properties on an animation that is already running. But what you could do is break the animation into short segments and change the speed for the next segment when the slider value changes.

Instead of animating from point A to point D, you'd animate from A-B, then B-C, then C-D. Use the parent class's animationDidStop to check the current point, check the slider value, and kick off the next animation.

This might produce jerky motion, but if you use very small segments, you might be able to smooth it out.

Wienke
  • 3,723
  • 27
  • 40
1

u should stop the animation and restart a new with a new duration time

but remember to log down the fromValue and the toValue , and use the old toValue as the new fromValue to perform a seamless change

chings228
  • 1,859
  • 24
  • 24
0

set speed as what you need.

    a.duration=0.5;

Try this...

Ayaz
  • 1,398
  • 15
  • 29
0

If you just want Autoscrolling text then you can also use one class

http://blog.stormyprods.com/2009/10/simple-scrolling-uilabel-for-iphone.html

It might also work in your case, try it.

Yogesh Maheshwari
  • 1,324
  • 2
  • 16
  • 37