I'm having a hard time figuring out how queue's work in jQuery, especially the fx
queue. What I want to do is:
Animate multiple different elements one after another
Take a look at this fiddle first. When you click on the button, both of the elements are being animated. Now I know I can do something like this fiddle, where I put the animation in the callback of the first animation, but this isn't an option because I have a situation where I have a pool of animations, and I want to arbitrarily run any of them in a particular sequence. For example, I might have animations A, B, C, D, and E which all animate different elements. Sometimes I will want to execute in the order B->A->C, another time I might want A->B->C.
How can I use queues开发者_JAVA技巧 to achieve this functionality?
Since your animations are moving different elements, you might be better off managing your own queue than doing it with jquery's. You could store the animations you want to run in an array.
animations = [animation_a, animation_b, animation_c];
and then at the end of each animation call the function which runs the next one. Like:
function run_next() {
if ( animations.length > 0 ) {
next_animation = animations.shift();
next_animation();
}
}
function animation_a() {
$("#element1").slideDown(500, run_next);
}
function animation_b() {
$("#element2").animate({left:'-=200'},1500, run_next);
}
See this fiddle.
Lets say that you have all the A,B,C...N have the same class just to select them in an array.
And each element has its animation property that you want to do with that.
Like we have a DIV
s :
<div class="animateMe" properties="{Left: +=50}" duration="2000", easing="linear"></div>
<div class="animateMe" properties="{Top: +=50}" duration="1000", easing="linear"></div>
Then selecting all the DIVs will be like.
var elements = $('div.animateMe') // Get all the objects in an array
Now there is a jQuery shuffle plugin that will help you in shuffling the array you have selected.
elements = $.shuffle( elements );
Now You can use .each()
function to animate individually.
$.each( elements, function(){
var properties = this.attr('properties');
var duration= this.attr('duration');
var easing= this.attr('easing');
this.animate( properties, duration, easing );
});
Update (working)
The code below does what you want; it is based off of the custom queue from Leopd. It does not use jQuery's queues or deferred objects though: http://jsfiddle.net/rkw79/FPGrj/
var q = ['div1', 'div2', 'div3', 'div4'];
var next_div = q.shift();
$("button").click( function() {
animate_div();
});
function animate_div() {
if ( q.length > 0 ) {
curr_div = next_div;
next_div = q.shift();
$('#' + curr_div).hide(2000,animate_div);
}
else {
$('#' + next_div).hide(2000);
}
}
The crossed out code was the original solution using deferred objects. It does not produce the functionality desired by the OP. It just serves to shorten the amount of code needed to chain multiple animations to a single object; it does not serve to chain animations across multiple objects
You want to make use of deferred objects. For your case, it is especially easy since animations are already creating promise objects: http://jsfiddle.net/rkw79/fpseA/
$("button").click( function() {
$('#div1').growWidth().growHeight();
});
$.fn.growWidth = function () {
return this.animate({width: 200});
}
$.fn.growHeight = function () {
return this.animate({height: 200});
}
精彩评论