Jquery Animation’s Synchronization and Nested Animation Using a Counter

Animation In Jquery is quite simple and easy to use. But things come complicated when you want to create a series of animations. Recently I am building an app which heavily relies on the animation, and get really exhausted sereral times. I learn a lot from this.

Animation Sync

Here is what I write at the very beginning.

$('#left').animate({left: '300px'}, 300, function(){
    $('#left #left-node').attr('id', 'center-node');
    $(this).attr('id', 'center');
    //...
});
$('#center').animate({left: '600px'}, 300, function(){
    $('#center #center-node').attr('id', 'right-node');
    $(this).attr('id', 'right');
    //...
});
$('#right').animate({left: '900px'}, 300, function(){$(this).remove();})

Three blocks will move right at the same time. Then left and center block will change their id to fit the new position. Then here comes the problem: although the three animations in different elements seem to finish at the same time, they finish one after another indeed. And I even don’t know which one! So the operations of changing the id will result in a mess. Needless to say other animation I want to do after.

I need a function that can be called after all these animations finish. I resort to the Queue in the Jquery but find the queue is binding to a particular element. Then a school mate tells me to use a counter and a shared callback to synchronize the animation. That’s quite a good idea. Then the code will be like this.

var sync = 3;
function callback(){
    if(--sync > 0) return;
    //...
}
$('#left').animate({left: '300px'}, 300, callback);
$('#center').animate({left: '600px'}, 300,callback);
$('#right').animate({left: '900px'}, 300, callback);

Nested Animation

As I dynamically generate the html, so I want to make the animation more beautiful. So I write this.

//...generate the html
$("#left-node .node, #center-node .node").hide().fadeIn(300, function(){
    $("#left-node").animate({left: '300px'}, 300);
    $("#center-node").animate({left: '600px'}, 300);
});

I want all the nodes to fade in and after that move the right position. Then the disaster occurred. Since the $() selector has selected more than one element, so the callback will be triggered more than once! Say 15 nodes have been selected, the left-node and the center-node will animate for 15 times! And the default animation queue in both element will function, that is to say, they will animate for 15*300 = 4500 ms. The worst part is, if any event trigger other animation on the two element, the upcoming animation will be held up till the repeated animation finish. The users will see a blocked response in their eyes.
This can also be fixed by the counter mentioned above.

var $nodes = $("#left-node .node, #center-node .node");
var sync = $nodes.size();
$nodes.hide().fadeIn(300, function(){
    if(--sync > 0) return;
    //... further animation
});

OK! All animations go as expected now. But this is really a hard work for a novice of JavaScript like me.

Well, maybe the best way to avoid these complicated cases is not to design so many animations in your web page.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>