我如何使用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/
所以,这是为什么这个工作,以及它在做什么:
-
对
$.globalQueue.queue()
的调用只是将一个调用排队到你的标签的animation,但是它将它排队在body标签上。 -
当jQuery在主体队列中点击你的标签animation时,你的标签的animation开始,在你的标签的队列中 – 但是jQueryanimation框架的工作方式,任何自定义的animationcallback都会导致标签的animation队列(在这种情况下是主体)停止,直到自定义animation调用传入的
dequeue()
函数。 所以,即使您的animation标签和主体的队列是分开的,body标签的队列现在正在等待它的dequeue()
被调用。 http://api.jquery.com/queue/#queue-queueName-callback -
我们只是通过调用它的
dequeue()
函数使标记的队列上的最后一个排队项目继续全局队列,这就是将队列连接在一起的原因。 -
为了方便起见,
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" }); });