我如何使用jQuery按顺序animation多个元素?

我认为这将是简单的,但我仍然无法得到它的工作。 通过点击一个button,我想要一个接一个地发生几个animation – 但现在所有的animation都是一次发生的。 这是我的代码 – 有人可以告诉我我要去哪里吗?

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

你可以做一堆callback。

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

队列只有在你animation相同的元素时才有效。 主知道为什么上面被投票了,但它不起作用。

您将需要使用animationcallback。 您可以将一个函数作为最后一个parameter passing给animation函数,并在animation完成后调用它。 但是,如果你有多个嵌套的animationcallback脚本将变得非常不可读。

我build议下面的插件重写原生jQuery的animationfunction,并允许您指定队列名称。 所有使用相同队列名称添加的animation将按照此处演示的顺序运行。

示例脚本

  $("#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对象的队列,以避免与其他无关的animation相冲突:

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

有一件事要记住,虽然我从来没有遇到这样做的问题,根据文档使用普通的对象包装队列方法是不正式支持。

使用普通对象

目前,包含在jQuery中的纯JavaScript对象支持的唯一操作是:.data(),prop(),bind(),.unbind(),.trigger()和.triggerHandler()。

根据jammus的回答,对于长序列的animation来说,这可能更实用一些。 发送一个列表,依次为每个animation添加animation,recursion地使用缩小列表再次调用animation。 全部完成后执行回叫。

这里的列表是选定的元素,但它可能是一个更复杂的对象列表,每个animation持有不同的animation参数。

这是一个小提琴

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

按顺序animation多个标签

你可以利用jQuery的内置animation队列,如果你只是select一个标签,如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/

所以,这是为什么这个工作,以及它在做什么:

  1. $.globalQueue.queue()的调用只是将一个调用排队到你的标签的animation,但是它将它排队在body标签上。

  2. 当jQuery在主体队列中点击你的标签animation时,你的标签的animation开始,在你的标签的队列中 – 但是jQueryanimation框架的工作方式,任何自定义的animationcallback都会导致标签的animation队列(在这种情况下是主体)停止,直到自定义animation调用传入的dequeue()函数。 所以,即使您的animation标签和主体的队列是分开的,body标签的队列现在正在等待它的dequeue()被调用。 http://api.jquery.com/queue/#queue-queueName-callback

  3. 我们只是通过调用它的dequeue()函数使标记的队列上的最后一个排队项目继续全局队列,这就是将队列连接在一起的原因。

  4. 为了方便起见, globalQueue.queue方法返回一个简单链接的引用。

的setInterval

为了完整起见,这里很容易find一个setInterval的替代方法 – 那就是你没有那么期望做出独立的animation坐标,就像随着时间的推移而不是在animation中引发奇怪的浪涌更新的浏览器将推迟animation队列和定时器来保存CPU。

你可以像下面这样replacesetInterval的调用:

 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/

并且当背景选项卡的浏览器重新启用其animation时,可以避免那些尴尬的animation爆发。

你也可以把你的效果放到同一个队列中,也就是BODY元素的队列中。

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

确保在最后一个效果callback中调用了dequeue()。

这已经得到了很好的回答(我认为jammus的答案是最好的),但我想我会提供另一种select,基于我如何在我的网站上做这个,使用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"); }); 

(用你想要的animation速度replace1000,这个想法是你的延迟函数延迟了这个数值,并在每个元素的animation中累积延迟,所以如果你的animation是500毫秒,你的延迟值是500,1000,1500)

编辑:FYI jquery的“慢”速度也是600毫秒。 所以如果你想在你的animation中仍然使用“缓慢”,那么在每个后续的延迟函数调用中使用这些值 – 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" }); });