2010-03-12 6 views
26

Disons que plusieurs animations sont exécutées en même temps et que je souhaite appeler une fonction une fois toutes les animations terminées.jQuery, rappel d'une seule fois après plusieurs animations

Avec une seule animation, c'est facile; il y a un rappel pour ça. Par exemple:

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

Problème, si mon sélecteur trouve plusieurs éléments, le rappel sera appelé pour chacun d'eux.

Une solution de contournement n'est pas trop difficile; par exemple:

<!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> 

Ma question est: est-il une meilleure façon de le faire?

+0

Dans la plupart des cas, j'utilise un booléen au lieu d'un compteur (donc l'action est effectuée à la fin de la première animation), sinon c'est la même méthode. Bonne question, je suis curieux d'autres façons. –

+0

En effet. Vous voulez tous les attendre si par exemple toutes vos animations ne sont pas de la même longueur (pas comme dans mon exemple simpliste), et vous voulez faire quelque chose seulement après que les choses s'arrêtent de bouger, ou fading sur votre navigateur. –

Répondre

29

Vous pouvez exécuter le même rappel pour tous, mais seulement d'exécuter la clause if si aucune sont actuellement plus animée, comme ceci:

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

Ce ne vérifie que le cas échéant sont toujours animés par la :animated selector. Si vous animez beaucoup de choses différentes alors utiliser le même concept, il suffit d'ajouter au sélecteur comme ceci:

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

Si vous utilisez dans beaucoup d'endroits, je fais que callback fonction onFinish ou quelque chose pour ranger.

+0

Nice, j'aime l'aspect définitif de ceci. –

+0

J'aime ça aussi, +1 –

+0

Ran dans ce problème aussi. Solution intelligente. –

3

Dans mon cas, je dois définir

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

Regardez la discussion sur ce fil: jQuery $.animate() multiple elements but only fire callback once

Le .when()/.then() et les fonctions .promise().done(callback()); offrent une solution beaucoup plus élégante au problème d'appeler un seul calllback à la fin de toutes les animations.

+12

Cela devrait être la bonne réponse. –

+1

Bon appel. De même, ceci utilise la file d'attente pour déclencher un rappel après que le dernier élément a été exécuté: elements.fadeOut (330) .last(). Queue (function() {}); – Tyler