2010-03-12 6 views
26

Diciamo che ho diverse animazioni in esecuzione contemporaneamente e voglio chiamare una funzione una volta che tutte sono finite.jQuery, chiamando una richiamata solo una volta dopo più animazioni

Con una sola animazione, è facile; c'è una richiamata per quello. Per esempio:

$(".myclass").fadeOut(slow,mycallback); 

Il problema è che, se il mio selettore trova diversi elementi, il callback verrà chiamata per ciascuno di essi.

Una soluzione non è troppo difficile; ad esempio:

<!DOCTYPE html> 
<html> 
<head> 
    <title>Example</title> 
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js"></script> 
    <script type="text/javascript"> 
    $(document).ready(function() { 
     var $mc=$(".myclass"),l=$mc.length; 
     $mc.fadeOut("slow",function(){ 
     if (! --l) $("#target").append("<p>All done.</p>"); 
     }); 
    }); 
    </script> 
    <style type="text/css"> 
    </style> 
</head> 
<body> 
    <p class="myclass">Paragraph</p> 
    <p class="myclass">Paragraph</p> 
    <p class="myclass">Paragraph</p> 
    <p class="myclass">Paragraph</p> 
    <p class="myclass">Paragraph</p> 
    <p class="myclass">Paragraph</p> 
    <div id="target"></div> 
</body> 
</html> 

La mia domanda è: c'è un modo migliore per farlo?

+0

Nella maggior parte dei casi, utilizzo un valore booleano anziché un contatore (quindi l'azione viene eseguita alla fine della prima animazione), ma altrimenti è lo stesso metodo. Bella domanda, sono curioso per altri modi. –

+0

Infatti. Si desidera attendere tutti se, ad esempio, tutte le animazioni non hanno la stessa lunghezza (non come nel mio esempio semplicistico) e si desidera fare qualcosa solo dopo che le cose si sono fermate o si sono sbiadite nel browser. –

risposta

29

È possibile eseguire lo stesso richiamo per tutti loro, ma eseguire solo la clausola if se Nessuno è attualmente in corso di animazione più, in questo modo:

$(".myclass").fadeOut("slow", function() { 
    if ($(".myclass:animated").length === 0) 
     $("#target").append("<p>All done.</p>"); 
    }); 

Questo solo controlla se ve ne sono ancora in corso di animazione attraverso il :animated selector. Se tu fossi animando un sacco di cose diverse quindi utilizzare lo stesso concetto, basta aggiungere al selettore in questo modo:

$(".myclass:animated, .myClass2:animated") 

Se lo si usa in un sacco di posti, mi piacerebbe fare che una funzione di callback onFinish o qualcosa da riordinare.

+0

Bello, mi piace l'aspetto definitivo di questo. –

+0

Mi piace anche questo, +1 –

+0

Anche in questo problema. Soluzione intelligente –

3

Nel mio caso devo definire

if ($(".myclass:animated").length === 1) 
42

Guardate la discussione su questo thread: jQuery $.animate() multiple elements but only fire callback once

Il .when()/.then() ei .promise().done(callback()); funzioni forniscono una soluzione molto più elegante al problema di chiamare un singolo calllback alla fine di tutte le animazioni.

+12

Questa dovrebbe essere la risposta corretta. –

+1

Buona chiamata. Allo stesso modo, questo usa la coda per attivare una richiamata dopo che l'ultimo elemento è stato eseguito: elements.fadeOut (330) .last(). Queue (function() {}); – Tyler