Как я могу анимировать несколько элементов последовательно с помощью 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");
});
Ответы
Ответ 1
Вы можете сделать кучу обратных вызовов.
$(".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");
});
});
});
});
Ответ 2
Очередь работает только при анимации одного и того же элемента. Господь знает, почему вышесказанное проголосовало, но оно не сработает.
Вам нужно будет использовать обратный вызов анимации. Вы можете передать функцию как последний параметр функции animate, и она будет вызвана после завершения анимации. Однако, если у вас есть несколько вложенных анимаций с обратными вызовами, script станет довольно нечитаемым.
Я предлагаю следующий плагин, который перезаписывает собственную функцию анимации jQuery и позволяет указать имя очереди. Все анимации, которые вы добавляете с одинаковым именем очереди, будут выполняться последовательно, как показано здесь.
Пример 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"});
Ответ 3
Я знаю, что это старый вопрос, но он должен быть обновлен с ответом на новые версии 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");
});
Ответ 4
Небольшое улучшение ответа @schmunk заключается в использовании очереди объектов jQuery с простым объектом, чтобы избежать конфликта с другими несвязанными анимациями:
$({})
.queue(function (next) {
elm1.fadeOut('fast', next);
})
.queue(function (next) {
elm2.fadeIn('fast', next);
})
// ...
Одна вещь, о которой следует помнить, состоит в том, что, хотя я никогда не сталкивался с такими проблемами, в соответствии с документами, используя методы очереди в обертке простого объекта, официально не поддерживается.
Работа с равными объектами
В настоящее время единственные операции, поддерживаемые на обычных объектах JavaScript, завернутых в jQuery являются:.data(), prop(), bind(),.unbind(),.trigger() и .triggerHandler().
Ответ 5
Расширение ответа на jammus, возможно, немного более практично для длинных последовательностей анимаций. Отправляйте список, оживляя каждый поочередно, рекурсивно вызывая ожидание снова с уменьшенным списком. Выполните обратный вызов, когда все будет завершено.
Здесь перечислены выбранные элементы, но это может быть список более сложных объектов, содержащих разные параметры анимации для анимации.
Вот скрипка
$(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);
});
}
Ответ 6
Анимация нескольких тегов последовательно
Вы можете задействовать встроенную анимацию анимации 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, любой пользовательский обратный вызов анимации вызывает очередь анимации тегов (тело в этом случае) для остановки, пока пользовательская анимация не вызовет функцию pass-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/
И избегайте этих неловких взрывов анимации, когда вкладка фона активирует свою анимацию браузером.
Ответ 7
Вы также можете поместить свои эффекты в одну и ту же очередь, то есть в очередь элемента BODY.
$('.images IMG').ready(
function(){
$('BODY').queue(
function(){
$('.images').fadeTo('normal',1,function(){$('BODY').dequeue()});
}
);
}
);
Убедитесь, что вы вызываете dequeue() в течение последнего обратного вызова эффекта.
Ответ 8
Это уже ответили хорошо (я думаю, что ответ 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 "медленная" скорость также равна 600 миллисекунд. поэтому, если вы хотите использовать "медленные" в своей анимации, просто используйте эти значения в каждом последующем вызове функции задержки - 600, 1200, 1800
Ответ 9
Я думал о возвращении решения.
Может быть, вы можете определить, что каждый объект имеет один и тот же класс, например .transparent
Затем вы можете создать функцию, скажем startShowing
, которая ищет первый элемент с классом .transparent
, .transparent
его, удаляет .transparent
и затем вызывает сама.
Я не могу гарантировать последовательность, но обычно следует за порядком, в котором был написан документ.
Это функция, которую я сделал, чтобы попробовать это
function startShowing(){
$('.pattern-board.transparent:first').animate(
{ opacity: 1},
1000,
function(){
$(this).removeClass('transparent');
startShowing();
}
);
}
Ответ 10
Используйте параметр 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" });
});