如何使用jQuery按顺序为多个元素设置动画?

lnv*_*vrt 32 queue jquery 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");
});
Run Code Online (Sandbox Code Playgroud)

red*_*are 29

队列仅在您动画相同元素时才有效.上帝知道上面为什么投了票,但是不行.

您将需要使用动画回调.您可以将函数作为最后一个参数传递给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"});
Run Code Online (Sandbox Code Playgroud)

  • 两个链接看起来都破了,请你检查一下@redsquare? (2认同)

Bil*_*rry 26

我知道这是一个老问题,但它应该更新为新的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;
}
Run Code Online (Sandbox Code Playgroud)

然后你可以像这样调用它:

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");        
});
Run Code Online (Sandbox Code Playgroud)

  • 这是一个非常好的模式.还有一个建议 - IE 8(至少)以不同的方式处理"参数"对象.首先,它需要成为一个真正的数组,然后.splice方法需要两个参数.使用var args = Array.prototype.slice.call(arguments); var rest = [] .splice.call(args,1,args.length-1); (2认同)

jam*_*mus 24

你可以做一堆回调.

$(".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");        
            });
        });
    });
});
Run Code Online (Sandbox Code Playgroud)

  • 我在我的网站上遇到了类似的问题,我从那时起就开始考虑使用回调,但这样做似乎有点不合适.如果你能以某种方式用jquery链接来做它会很好.目前我使用延迟功能:首先制作动画.把第二件事延迟了相同的时间我动画第一件事,然后给它制作动画......依此类推. (4认同)

pgr*_*ham 6

@ schmunk的答案略有改进是使用普通对象jQuery对象的队列,以避免与其他不相关的动画冲突:

$({})
    .queue(function (next) {
        elm1.fadeOut('fast', next);
    })
    .queue(function (next) {
        elm2.fadeIn('fast', next);
    })
    // ...
Run Code Online (Sandbox Code Playgroud)

要记住的一件事是,虽然我从来没有遇到过这样的问题,但根据在普通对象包装器上使用队列方法的文档并没有得到官方支持.

使用普通对象

目前,jQuery包装的普通JavaScript对象支持的唯一操作是:.data(),. prop(),. bind(),. unbind(),. turigger()和.triggerHandler().

  • 这是一个优雅的解决方案,因为它避免了深度嵌套回调.我汇集了一些[jsFiddle](http://jsfiddle.net/philippm/SFLAB/),将其付诸行动.关于包装普通对象的支持:[这个官方jQuery教程](http://learn.jquery.com/effects/uses-of-queue-and-dequeue/)使用相同的方法. (2认同)