Как можно последовательно анимировать несколько элементов с помощью jQuery?
Я думал, что это будет просто, но я все еще не могу заставить его работать. Нажав одну кнопку, Я хочу, чтобы произошло несколько анимаций - одна за другой - но теперь все анимации происходят одновременно. Вот мой код - может кто-нибудь, пожалуйста, сказать мне, где я ошибаюсь?:
$(".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");
});
9 ответов:
Вы можете сделать кучу обратных вызовов.
$(".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"); }); }); }); });
Очередь работает только в том случае, если вы анимируете один и тот же элемент. Бог знает, почему за это проголосовали, но это не сработает.
Вам нужно будет использовать обратный вызов анимации. Вы можете передать функцию в качестве последнего парама функции animate, и она будет вызвана после завершения анимации. Однако если у вас есть несколько вложенных анимаций с обратными вызовами, сценарий будет довольно нечитабельным.
Я предлагаю следующий плагин, который перезаписывает родной jQuery animate функция и позволяет указать имя очереди. Все анимации, которые вы добавляете с тем же именем очереди, будут выполняться последовательно, как показано здесь .
Пример сценария
$("#1").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); $("#2").animate({marginTop: "100px"}, {duration: 100, queue: "global"}); $("#3").animate({marginTop: "100px"}, {duration: 100, queue: "global"});
Я знаю, что это старый вопрос, но он должен быть обновлен с ответом для более новых версий jQuery (1.5 и выше):
Используя функцию
$.when, Вы можете написать этот помощник: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; }Тогда вы можете назвать это так:
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"); });
Небольшое улучшение в ответе @schmunk заключается в использовании простой очереди объекта jQuery, чтобы избежать конфликта с другими несвязанными анимациями:
$({}) .queue(function (next) { elm1.fadeOut('fast', next); }) .queue(function (next) { elm2.fadeIn('fast', next); }) // ...Следует иметь в виду, что, хотя я никогда не сталкивался с проблемами при этом, согласно docs Использование методов очереди на простой оболочке объекта официально не поддерживается.
Работа С Простыми Объектами
В настоящее время поддерживаются только операции на обычном JavaScript объекты, завернутые в jQuery АР: .данные(),.прислонить(),.связывать(), .развязывать(), .триггер и .triggerHandler().
Продолжая ответ джаммуса, это, возможно, немного более практично для длинных последовательностей анимаций. Отправьте список, анимируйте каждого по очереди, рекурсивно вызывая animate снова с уменьшенным списком. Выполните обратный вызов, когда все закончено.
Список здесь состоит из выбранных элементов, но это может быть список более сложных объектов, содержащих различные параметры анимации для каждой анимации.
$(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); }); }
Анимация Нескольких Тегов Последовательно
Вы можете использовать встроенную анимационную очередь jQuery, если просто выберете тег, подобный body, чтобы сделать глобальную очередь:
// 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/
Итак, вот почему это работает, и что это делает:
Вызов
$.globalQueue.queue()- это просто очередь вызова анимации вашего тега,но он ставит ее в очередь на теге body.Когда jQuery попадает в ваш тег анимация в теле очередь, анимация вашего тега запускается в очереди для вашего тега - но так, как работает jQuery animation framework, любой обратный вызов пользовательской анимации вызывает остановку очереди анимации тега (в данном случае тела), пока пользовательская анимация не вызовет функцию passed-in
dequeue(). Таким образом, несмотря на то, что очереди для вашего анимированного тега и тела разделены, очередь тега тела теперь ожидает вызова егоdequeue(). http://api.jquery.com/queue/#queue-queueName-callbackМы просто делаем последний элемент очереди в очереди тега вызовом для продолжения глобальной очереди, вызывая его функцию
dequeue()- это то, что связывает очереди вместе.Для удобства метод
globalQueue.queueвозвращает ссылкуthisдля упрощения цепочки.SetInterval
Для полноты картины здесь легко приземлиться, просто ища альтернативу
setInterval- этому вы не столько хотите сделать отдельные анимации координированными, сколько просто запустить их с течением времени без странного всплеска вперед в вашей анимации, вызванного тем, как новые браузеры отложат очереди анимации и таймеры, чтобы сэкономить процессор.Вы можете заменить вызов на
setIntervalследующим образом:setInterval(doAthing, 8000);С этим:
/** * 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/
И избегайте этих неловких взрывов анимации, когда фоновая вкладка имеет свою анимацию повторно включается браузером.
Вы также можете поместить свои эффекты в ту же очередь, то есть очередь элемента BODY.
$('.images IMG').ready( function(){ $('BODY').queue( function(){ $('.images').fadeTo('normal',1,function(){$('BODY').dequeue()}); } ); } );Убедитесь, что вы вызываете dequeue () в последнем эффекте обратного вызова.
На этот вопрос уже был дан хороший ответ (я думаю, что ответ jammus является лучшим), но я подумал, что предложу другой вариант, основанный на том, как я делаю это на своем веб-сайте, используя функцию
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"); });(Замените 1000 на нужную скорость анимации. идея заключается в том, что ваша функция задержки задерживает на эту величину и накапливает задержку в анимации каждого элемента, поэтому, если бы ваши анимации были каждые 500 миллисекунд, ваши значения задержки были бы 500, 1000, 1500)
Edit: FYI jquery 'slow' скорость также составляет 600 миллисекунд. поэтому, если вы хотите использовать 'slow' все еще в ваших анимациях, просто используйте эти значения в каждом последующем вызове функции задержки-600, 1200, 1800
Используйте опцию
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" }); });
Comments