I'm trying to create an animation sequence with jQuery where one animation starts after the previous one is done. But I just can't wrap my head around it. I've tried to make use of the jQuery.queue, but I don't think I can use that because it seems to have one individual queue for each element in the jQuery array.
I need something like:
$('li.some').each(function(){
// Add to queue
$(this).animate({ width: '+=100' }, 'fast', function(){
// Remove from queue
// Start next animation
});
});
Is there a jQuery way to do this or do I have to write and handle my own queue manually?
You can make a custom .queue()
to avoid the limitless nesting..
var q = $({});
function animToQueue(theQueue, selector, animationprops) {
theQueue.queue(function(next) {
$(selector).animate(animationprops, next);
});
}
// usage
animToQueue(q, '#first', {width: '+=100'});
animToQueue(q, '#second', {height: '+=100'});
animToQueue(q, '#second', {width: '-=50'});
animToQueue(q, '#first', {height: '-=50'});
Demo at http://jsfiddle.net/gaby/qDbRm/2/
If, on the other hand, you want to perform the same animation for a multitude of elements one after the other then you can use their index to .delay()
each element's animation for the duration of all the previous ones..
$('li.some').each(function(idx){
var duration = 500;
$(this).delay(duration*idx).animate({ width: '+=100' }, duration);
});
Demo at http://jsfiddle.net/gaby/qDbRm/3/
The callback of .animate() actually accepts another .animate(), so all you would have to do would be
$(this).animate({ width: '+=100' }, 'fast', function(){
$(selector).animate({attr: val}, 'speed', function(){
});
});
and so on.
You could call the next one recursively.
function animate(item) {
var elem = $('li.some').eq(item);
if(elem.length) {
elem.animate({ width: '+=100' }, 'fast', function() {
animate(item + 1);
});
}
}
animate(0);
why not build up a queue?
var interval = 0; //time for each animation
var speed = 200;
$('li.some').each(function(){
interval++;
$(this).delay(interval * speed).animate({ width: '+=100' }, speed);
});
EDIT: added speed param
Thanks to everybody replying!
I thought I should share the outcome of my question. Here is a simple jQuery slideDownAll plugin that slides down one item at a time rather than all at once.
(function ($) {
'use strict';
$.fn.slideDownAll = function (duration, callback) {
var that = this, size = this.length, animationQueue = $({});
var addToAnimationQueue = function (element, duration, easing, callback) {
animationQueue.queue(function (next) {
$(element).slideDown(duration, easing, function () {
if (typeof callback === 'function') {
callback.call(this);
}
next();
});
});
};
return this.each(function (index) {
var complete = null,
easing = 'linear';
if (index + 1 === size) {
complete = callback;
easing = 'swing';
}
addToAnimationQueue(this, duration / size, easing, complete);
});
};
} (jQuery));
Not very well test, but anyways.
Enjoy!!