Come posso animare più elementi in sequenza usando jQuery?

Ho pensato che sarebbe stato semplice ma non riesco ancora a farlo funzionare. Facendo clic su un pulsante, voglio che avvengano diverse animazioni – una dopo l’altra – ma ora tutte le animazioni stanno accadendo contemporaneamente. Ecco il mio codice: qualcuno può dirmi dove sto andando male ?:

$(".button").click(function(){ $("#header").animate({top: "-50"}, "slow") $("#something").animate({height: "hide"}, "slow") $("ul#menu").animate({top: "20", left: "0"}, "slow") $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow"); }); 

Potresti fare un sacco di callback.

 $(".button").click(function(){ $("#header").animate({top: "-50"}, "slow", function() { $("#something").animate({height: "hide"}, "slow", function() { $("ul#menu").animate({top: "20", left: "0"}, "slow", function() { $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow"); }); }); }); }); 

La coda funziona solo se si sta animando lo stesso elemento. Il Signore sa perché è stato votato, ma non funzionerà.

Sarà necessario utilizzare la richiamata dell’animazione. È ansible passare una funzione come ultimo parametro alla funzione di animazione e verrà richiamata al termine dell’animazione. Tuttavia, se hai più animazioni nidificate con callback, lo script diventerà piuttosto illeggibile.

Suggerisco il seguente plug-in che riscrive la funzione nativa di jQuery e consente di specificare un nome di coda. Tutte le animazioni che aggiungi con lo stesso nome di coda verranno eseguite in sequenza come mostrato qui .

Script di esempio

  $("#1").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); $("#2").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); $("#3").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); 

So che questa è una vecchia domanda, ma dovrebbe essere aggiornata con una risposta per le nuove versioni di jQuery (1.5 e successive):

Usando la funzione $.when puoi scrivere questo helper:

 function queue(start) { var rest = [].splice.call(arguments, 1), promise = $.Deferred(); if (start) { $.when(start()).then(function () { queue.apply(window, rest); }); } else { promise.resolve(); } return promise; } 

Quindi puoi chiamarlo così:

 queue(function () { return $("#header").animate({top: "-50"}, "slow"); }, function () { return $("#something").animate({height: "hide"}, "slow"); }, function () { return $("ul#menu").animate({top: "20", left: "0"}, "slow"); }, function () { return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow"); }); 

Un leggero miglioramento della risposta di @ schmunk è l’uso di una coda dell’object jQuery di object semplice per evitare conflitti con altre animazioni non correlate:

 $({}) .queue(function (next) { elm1.fadeOut('fast', next); }) .queue(function (next) { elm2.fadeIn('fast', next); }) // ... 

Una cosa da tenere a mente è che, sebbene non abbia mai incontrato problemi nel fare ciò, secondo i documenti che usano i metodi di coda su un semplice object wrapper non è ufficialmente supportato.

Lavorare con oggetti semplici

Al momento, le sole operazioni supportate su oggetti JavaScript semplici avvolti in jQuery sono: .data () ,. prop () ,. bind (), .unbind (), .trigger () e .triggerHandler ().

Estendendo la risposta di jammus, questo è forse un po ‘più pratico per lunghe sequenze di animazioni. Invia una lista, anima ciascuno a turno, chiamando ricorsivamente di nuovo l’animazione con una lista ridotta. Esegui una richiamata quando tutto è finito.

L’elenco qui è di elementi selezionati, ma potrebbe essere un elenco di oggetti più complessi che contengono parametri di animazione diversi per animazione.

Ecco un violino

 $(document).ready(function () { animate([$('#one'), $('#two'), $('#three')], finished); }); function finished() { console.log('Finished'); } function animate(list, callback) { if (list.length === 0) { callback(); return; } $el = list.shift(); $el.animate({left: '+=200'}, 1000, function () { animate(list, callback); }); } 

Animare più tag in sequenza

Puoi sfruttare l’accodamento di animazione incorporato di jQuery, se selezioni solo un tag come body per fare l’accodamento globale:

 // Convenience object to ease global animation queueing $.globalQueue = { queue: function(anim) { $('body') .queue(function(dequeue) { anim() .queue(function(innerDequeue) { dequeue(); innerDequeue(); }); }); return this; } }; // Animation that coordinates multiple tags $(".button").click(function() { $.globalQueue .queue(function() { return $("#header").animate({top: "-50"}, "slow"); }).queue(function() { return $("#something").animate({height: "hide"}, "slow"); }).queue(function() { return $("ul#menu").animate({top: "20", left: "0"}, "slow"); }).queue(function() { return $(".trigger").animate({height: "show", top: "110", left: "0"}, "slow"); }); }); 

http://jsfiddle.net/b9chris/wjpL31o0/

Quindi, ecco perché funziona e cosa sta facendo:

  1. La chiamata a $.globalQueue.queue() è solo in coda una chiamata all’animazione del tag, ma la accoda nel tag body.

  2. Quando jQuery colpisce l’animazione del tag nella coda del corpo, l’animazione del tag inizia, in coda per il tag, ma il modo in cui funziona il framework di animazione jQuery, qualsiasi callback di animazione personalizzata provoca l’arresto della coda di animazione di un tag (il corpo in questo caso) , finché l’animazione personalizzata non chiama la funzione dequeue() passata. Pertanto, anche se le code per il tag e il corpo animati sono separati, la coda del tag body è in attesa del dequeue() suo dequeue() . http://api.jquery.com/queue/#queue-queueName-callback

  3. Facciamo in modo che l’ultimo elemento in coda sulla coda del tag sia una chiamata per continuare la coda globale chiamando la sua funzione dequeue() – questo è ciò che lega le code insieme.

  4. Per comodità, il metodo globalQueue.queue restituisce un riferimento per una facile concatenazione.

setInterval

Per motivi di completezza, è facile atterrare qui solo cercando un’alternativa a setInterval – cioè non cerchi tanto di coordinare animazioni separate, ma semplicemente di accenderle nel tempo senza la strana ondata in avanti nella tua animazione causata dal i browser più recenti rimandano code e timer di animazione per risparmiare CPU.

Puoi sostituire una chiamata a setInterval questo modo:

 setInterval(doAthing, 8000); 

Con questo:

 /** * Alternative to window.setInterval(), that plays nicely with modern animation and CPU suspends */ $.setInterval = function (fn, interval) { var body = $('body'); var queueInterval = function () { body .delay(interval) .queue(function(dequeue) { fn(); queueInterval(); dequeue(); // Required for the jQuery animation queue to work (tells it to continue animating) }); }; queueInterval(); }; $.setInterval(doAthing, 8000); 

http://jsfiddle.net/b9chris/h156wgg6/

Ed evitare quegli scomodi attacchi di animazione quando una scheda di sfondo ha le sue animazioni riabilitate dal browser.

Puoi anche mettere i tuoi effetti nella stessa coda, cioè la coda dell’elemento BODY.

 $('.images IMG').ready( function(){ $('BODY').queue( function(){ $('.images').fadeTo('normal',1,function(){$('BODY').dequeue()}); } ); } ); 

Assicurati di chiamare dequeue () all’interno dell’ultimo callback dell’effetto.

Ho già risposto bene (penso che la risposta di jammus sia la migliore) ma ho pensato di fornire un’altra opzione in base a come faccio questo sul mio sito web, usando la funzione delay()

  $(".button").click(function(){ $("#header").animate({top: "-50"}, 1000) $("#something").delay(1000).animate({height: "hide"}, 1000) $("ul#menu").delay(2000).animate({top: "20", left: "0"}, 1000) $(".trigger").delay(3000).animate({height: "show", top: "110", left: "0"}, "slow"); }); 

(sostituisci 1000 con la tua velocità di animazione desiderata: l’idea è che i ritardi della funzione di ritardo di tale quantità e accumulino il ritardo nell’animazione di ciascun elemento, quindi se le tue animazioni fossero ogni 500 millisecondi i tuoi valori di ritardo sarebbero 500, 1000, 1500)

modifica: la velocità ‘lenta’ di FYI jquery è anch’essa di 600 millisecondi. quindi se volevi usare ‘slow’ ancora nelle tue animazioni usa semplicemente questi valori in ogni chiamata successiva alla funzione delay – 600, 1200, 1800

Usa l’opzione della queue :

 $(".button").click(function(){ $("#header").animate({top: "-50"}, { queue: true, duration: "slow" }) $("#something").animate({height: "hide"}, { queue: true, duration: "slow" }) $("ul#menu").animate({top: "20", left: "0"}, { queue: true, duration: "slow" }) $(".trigger").animate({height: "show", top: "110", left: "0"}, { queue: true, duration: "slow" }); });