Using jQuery.queue with multiple element animation

2020-02-09 00:34发布

问题:

jQuery queue's are very annoying - I can't get my head around it...

The following function contains 4 animations which I want to happen one after the other (not at the same time).

function startupAnime() {

    $("#header").animate({"opacity":"1"},{duration:3000, queue:"global"});
    $("#header").animate({"top":"0px"},{duration:3000, queue:"global"});
    &("#loader").animate({"opacity":"0"},{duration:3000, queue:"global"});
    $("#background").animate({"background-position" : "300px center"},{duration:3000, queue:"global"});
}

$(window).load(function() { 

    startupAnime();
})

The two #header elements will animate one after the other, but the rest all happen at the same time.

I then found out the Queue only works if your animating the same element!! That's not very useful... But adding queue:"name" apparently is supposed to link them into the same queue... although this just stops them from working for me.

Am I missing something here? I'm not sure if queue means 'next animation will start when current one is finished', or 'these animations are being held in a queue waiting for you to release them' by maybe calling queue("global") or something!?

Most suggestions talk about animating one element, or setting up many functions and using callback to 'iterate' through the functions - not very clean if you ask me. I simply want to be able to run a list of animations whenever I ask for it.

NB: A 'list' of animations might animate elements one at a time, but I also might want two or more elements to animate at the same time at some point in the list. Here's a sample:

animate element A
-> then ->
animate element B
-> then ->
animate element C and D together
-> then ->
animate element E

回答1:

You have a lot of options, but here is what I would do (because I like the self-explanatory syntax):

$.when(
    $("#header").animate({opacity: 1}, 3000).promise(),
    $("#header").animate({top: 0}, 3000).promise()
).done(function() {
    $("#loader").animate({opacity: 0}, 3000).promise()
    .done(function() {
        $("#background").animate({"background-position" : "300px center"}, 3000)
    })
})

Demo: http://jsfiddle.net/vjazX/



回答2:

You have a few options.

Delay it:

$("#loader").delay(6000).animate({"opacity":"0"},{duration:3000});
$("#background").delay(9000).animate({"background-position" : "300px center"},{duration:3000});

Use callbacks:

function startupAnime() {

    $("#header").animate({"opacity":"1"},3000);
    $("#header").animate({"top":"0px"},3000,function(){
        $("#loader").animate({"opacity":"0"},3000,function(){
            $("#background").animate({"background-position" : "300px center"},3000);
        });
    });   

}

or use deferred objects:

function startupAnime() {

    $("#header").animate({"opacity":"1"},3000);
    $("#header").animate({"top":"0px"},3000).promise().done(function(){
        $("#loader").animate({"opacity":"0"},3000).promise().done(function(){
            $("#background").animate({"background-position" : "300px center"},3000);
        });
    });   

}

Another deferred object option:

function startupAnime() {

    $("#header").animate({"opacity":"1"},3000);
    $("#header").animate({"top":"0px"},3000).promise().then(function(){
        return $("#loader").animate({"opacity":"0"},3000).promise();
    }).done(function(){
        $("#background").animate({"background-position" : "300px center"},3000);
    });

}  

I won't even post the custom queueing because that just gets ridiculous.

None of them are really very clean. Pick your poison. The .delay() looks the cleanest to me, but may be less maintainable. Though the alternatives aren't that maintainable either.

If i had to, I would use the 2nd deferred object sample because i don't feel comfortable with the delay and hate the pyramid of doom.



回答3:

Try using jQuery promise API. You can pull the promise from each jQuery element and then attach a done callback to it.

For example,

$("#header").animate({"opacity":"1"},{duration:3000 }).promise().done(function () {
    $("#header").animate({ "top":"0px" },{ duration:3000 });
});

You can refer to jQuery's promise API for more information. http://api.jquery.com/promise/