2012-02-27 25 views
5

non posso usare le richiamate perché ho uno scenario come questo (pseudo-codice):Animazioni sincrone in jQuery, non utilizzando i callback?

$('.box').on('click', function() { 
    $('.expanded-box').animate({ 
     // shrink it 
    }); 

    $(this).animate({ 
     // grow it 
     $(this).addClass('expanded-box'); 
    }); 
}); 

non riesco a mettere l'animazione di espansione all'interno del callback per l'animazione expanded-box crescita, perché essa non può sempre accadere . Ma ho bisogno che la seconda animazione attenda fino a quando il precedente non è finito. Come posso fare questo?

+0

Che cosa si intende per "non sempre può accadere."? Intendi che '.expanded-box' potrebbe non esistere? –

risposta

7

Dal jQuery 1.6, è possibile utilizzare promise() per ottenere un Promise object che sarà risolto quando tutte le animazioni su un determinato elemento sono state completate. Inoltre, la documentazione dice:

L'utilizzo di .promise() su una raccolta senza animazione attiva restituisce una promessa risolta in .

, pertanto è ben adatto al vostro caso d'uso, e si può scrivere:

$('.box').on('click', function() { 
    var $this = $(this); 
    $('.expanded-box').animate({ 
     // shrink it 
    }).promise().done(function() { 
     $this.animate({ 
      // grow it 
     }).addClass('expanded-box'); 
    }); 
}); 
+0

Cool, non sapevo nemmeno di 'promise()' - grazie! Funziona anche su molti metodi diversi. – CaptSaltyJack

+0

In che modo è diverso inserire la seconda parte nel callback completo della prima animazione? – nnnnnn

+1

@nnnnnnn, se '$ (". Expanded-box ")' non corrisponde a nulla, il callback 'complete' non verrà chiamato, come viene chiamato una volta per ogni elemento abbinato. D'altra parte, 'promise()' restituisce un oggetto 'Promise' risolto se viene chiamato su un oggetto jQuery vuoto, quindi assicurandosi che la funzione passata a' done() 'venga chiamato in tutti i casi (cioè anche al primo clic, quando nessuna casella è stata espansa ancora). –

1

È possibile incapsulare il codice della seconda animazione in una funzione e quindi chiamare tale funzione dal callback della prima animazione o chiamarlo se la prima animazione non si verifica. Supponendo che l'idea è quello di ridurre qualche altro controllo che aveva la classe "espansa-box" da un precedente scatto:

$('.box').on('click', function() { 
    var $this = $(this), 
     $exp = $(".expanded-box"); 

    function grow() { 
     $this.animate({ 
      width: "200px", height: "100px" 
     }).addClass('expanded-box'); 
    } 

    if ($exp.length > 0) { 
     $exp.animate({ 
      width: "100px", height: "50px" 
     }, grow).removeClass("expanded-box"); 
    } else { 
     grow(); 
    }   
});​ 

Demo: http://jsfiddle.net/PXddm/

+0

Freddo. Ci avevo pensato, ma speravo in una soluzione più elegante. Ho pensato che esistesse una sorta di funzionalità di coda di animazione in jQuery. – CaptSaltyJack

+0

Esiste sicuramente una funzione di coda animnation. Si applicava solo per elemento, ma "A partire da jQuery 1.7, l'opzione di coda può anche accettare una stringa, nel qual caso l'animazione viene aggiunta alla coda rappresentata da quella stringa." - ma non ho mai usato quella funzione quindi non sono sicuro di come funzioni. – nnnnnn