Comment puis-je animer plusieurs éléments séquentiellement en utilisant jQuery?

je pensais que ce serait simple mais je n'arrive toujours pas à le faire fonctionner. En cliquant sur un bouton, je veux que plusieurs animations se produisent -l'un après l'autre - mais maintenant toutes les animations se produisent en même temps. Voici mon code-est-ce que quelqu'un peut me dire où je vais mal?:

$(".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");
});
31
demandé sur redsquare 2009-08-02 08:28:27

9 réponses

Vous pourriez faire un tas de rappels.

$(".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");        
            });
        });
    });
});
24
répondu jammus 2009-08-02 09:15:47

Queue ne fonctionne que si vous animez le même élément. Dieu sait pourquoi ce qui précède a été voté, mais ça ne marchera pas.

vous devrez utiliser l'animation callback. Vous pouvez passer une fonction comme le dernier paramètre à la fonction animate et il sera appelée une fois l'animation terminée. Cependant, si vous avez plusieurs animations imbriquées avec des callbacks, le script deviendra plutôt illisible.

je suggère le suivant plugin qui réécrit le jQuery natif anime la fonction et vous permet de spécifier un nom de file d'attente. Toutes les animations que vous ajoutez avec le même nom de file seront exécutées séquentiellement comme démontré ici.

exemple de script

  $("#1").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#2").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
  $("#3").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
28
répondu redsquare 2009-08-02 10:01:19

je sais que c'est une vieille question, mais il doit être mis à jour avec une réponse pour les nouvelles versions de jQuery (1.5):

$.when fonction, vous pouvez écrire ce 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;
}

Ensuite, vous pouvez l'appeler comme ceci:

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");        
});
25
répondu Bill Barry 2012-07-06 00:30:27

une légère amélioration par rapport à la réponse de @schmunk est d'utiliser la file d'attente d'un objet jQuery afin d'éviter tout conflit avec d'autres animations sans rapport:

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

Une chose à garder à l'esprit est que, bien que je n'ai jamais couru dans des problèmes, selon la documentation l'utilisation des méthodes de file d'attente sur un simple papier d'emballage n'est pas officiellement prise en charge.

Travailler Avec Des Objets Simples

à l'heure actuelle, le seul opérations prises en charge sur des objets JavaScript simples enveloppés dans du jQuery être. :données.,)(prop (),.lier. ,)(unbind (),.trigger() et .triggerHandler ().

6
répondu pgraham 2013-01-08 17:48:42

Extension sur jammus réponse, c'est peut-être un peu plus pratique pour de longues séquences d'animations. Envoyer une liste, animer chacun à son tour, appeler de nouveau de façon récursive animer avec une liste réduite. Exécutez un rappel lorsque tout est terminé.

la liste ici est des éléments sélectionnés, mais il pourrait s'agir d'une liste d'objets plus complexes contenant différents paramètres d'animation par animation.

Voici un violon

$(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);
    });
}
2
répondu Sean 2012-06-26 15:17:09

Animer Plusieurs Tags Séquentiellement

vous pouvez utiliser l'animation intégrée de jQuery en file d'attente, si vous sélectionnez simplement une balise comme body pour faire la file d'attente 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/

Donc, voilà pourquoi cela fonctionne, et ce qu'il fait:

  1. L'appel à $.globalQueue.queue() n'est qu'un appel à l'animation de votre tag, mais il fait la queue sur le corps balise.

  2. lorsque jQuery tape votre animation de tag dans la file d'attente body, l'animation de votre tag Commence, sur la file d'attente de votre tag - mais la façon dont le framework d'animation jQuery fonctionne, tout callback personnalisé d'animation provoque une file d'attente d'animation de tag (le corps dans ce cas) à s'arrêter, jusqu'à ce que l'animation personnalisée appelle le pass-in dequeue() fonction. Donc, même si les files d'attente pour votre étiquette animée et votre corps sont séparés, la file d'attente de la étiquette du corps attend maintenant pour son dequeue() appelé. http://api.jquery.com/queue/#queue-queueName-callback

  3. nous faisons juste le dernier élément de la file d'attente de la tag un appel pour continuer la file d'attente globale en appelant son dequeue() fonction-c'est ce qui relie les files d'attente.

  4. Pour plus de confort le globalQueue.queue la méthode retourne un this référence pour un enchaînement facile.

setInterval

Par souci d'exhaustivité, il est facile d'atterrir ici à la recherche d'une alternative à setInterval - c'est-à-dire que vous n'êtes pas tellement à la recherche de coordonner des animations séparées, comme juste les lancer au fil du temps sans l'étrange surtension en avant dans votre animation causée par la façon dont les nouveaux navigateurs reporteront les files d'attente d'animation et les minuteries pour sauver CPU.

Vous pouvez remplacer un appel à setInterval comme ceci:

setInterval(doAthing, 8000);

Avec ceci:

/**
 * 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/

et d'éviter ces sauts d'animation maladroits quand un onglet de fond a ses animations réactivées par le navigateur.

2
répondu Chris Moschini 2014-10-19 10:10:08

Vous pouvez également mettre vos effets dans la même file d'attente, c'est-à-dire la file d'attente de L'élément BODY.

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

assurez-vous d'appeler dequeue() dans le dernier effet callback.

1
répondu schmunk 2010-04-30 19:01:29

ceci a déjà été bien répondu (je pense que la réponse de jammus est la meilleure) mais j'ai pensé que je fournirais une autre option basée sur la façon dont je fais ceci sur mon site web, en utilisant le delay() fonction...

  $(".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");
});

(remplacez 1000 par la vitesse d'animation désirée. l'idée est que votre fonction de retard retarde de ce montant et accumule le retard dans l'animation de chaque élément, donc si vos animations étaient toutes les 500 millisecondes vos valeurs de retard seraient 500, 1000, 1500)

modifier: La vitesse "lente" de FYI jquery est aussi de 600milisecondes. donc si vous voulez utiliser 'slow' encore dans vos animations, utilisez simplement ces valeurs dans chaque appel ultérieur à la fonction delay-600, 1200, 1800

1
répondu MrVimes 2011-08-14 21:06:14

queue option:

$(".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" });
});
-8
répondu Garrett 2009-08-02 04:31:34