Change jQuery animation duration during animation

Is it possible to change the duration currently running jQuery animation between two different values?

I tried changing the duration using direct assignment but did not succeed:

 var timing = { duration: 4000 }; $(document).click(function (e) { timing.duration = 1000; }); $('#foo').animate({top:200, left:200}, timing); 

... and even, changing the fx.options.duration in step method does not affect the current animation:

 var state = false, $(document).click(function (e) { state = true; }); $('#foo').animate({top:200, left:200}, { duration: 4000, step: function(now, fx){ if(state) fx.options.duration = 1000; console.log(fx.options.duration); // 1000 } }); 

Here's a fiddle to play with. Any ideas how to do this?

+6
source share
2 answers

Duration is passed by value, not by reference. Therefore, animate does not store a link to duration . Even if you update the options object (which is passed by reference), jQuery uses options.duration internally, which means that it will be passed by value.

As a quick fix, you can stop the animation and restart it with a new duration - a setting for part of an already completed animation.

You will need to think about how you want it to behave, for example, when you increase the animation by 4 seconds to a 2-second animation in 3 seconds. In the code below, the animation will be immediate. Thinking about it, maybe this is not what you want, since you probably really care about speed, not duration.

The code below is a rough sketch, I'm not sure how accurate it is if it works when reducing animation values ​​or how it handles multiple animation values. You can also change the duration only once.

 var state = false, duration = 8000; $(document).click(function (e) { state = true; duration = 1000; }); var animationCss = {top:200, left:200}; $('#foo').animate(animationCss, { duration: duration, step: function(now, fx){ if(state) { $("#foo").stop(); var percentageDone = (fx.now - fx.start) / (fx.end - fx.start) var durationDone = fx.options.duration * percentageDone; var newDuration = duration - durationDone; if (newDuration < 0) { newDuration = 0; } $("#foo").animate(animationCss, { duration: newDuration}) } } }); 

http://fiddle.jshell.net/5cdwc/3/

+9
source

I'm probably a bit late for op, but since I ended up here trying to do the same, someone else might as well.

In the start() callback, jQuery passes the animation object as an argument, so you just need to save the link somewhere, and then you can change it to step() callback.

Sort of:

 var animEnd = false; //this will be updated somewhere else var animObj; $().animate({ width: '100%' }, { start: function(animation){ animObj = animation; }, step: function(now, tween){ if(!animEnd) //jquery set an interval of 13 but let be safe animObj.duration += 30; //you can change the value of tween.pos aswell } } ); 

Now the tricky part is that jQuery decides to stop or continue the animation before calling the step() callback. Thus, the duration is set for the next tick, and if it has not been set long enough, the animation can be stopped.
jQuery uses setInterval() with an interval of 13, so theoretically step() should be called every 13 ms, but since nothing is guaranteed, I think the duration should be increased by 30 ms at least.
Personally, I would even go at least 100. It is better to have an animation that works for too long (100 ms is almost imperceptible), rather than stopping too quickly.

0
source

All Articles