【问题标题】:Jquery - defer callback until multiple animations are completeJquery - 延迟回调直到多个动画完成
【发布时间】:2011-07-10 09:41:26
【问题描述】:

我需要在多个元素完成动画后执行一次回调。 我的 jquery 选择器如下:

$('.buttons').fadeIn('fast',function() {
   // my callback
});

这样做的问题是按钮类匹配了许多元素,所有这些元素都需要在执行回调之前淡入。就目前而言,回调是在每个单独的元素完成动画后执行的。这不是所需的功能。我正在寻找一个优雅的解决方案,这样我的回调只在所有匹配的元素完成动画后执行一次。这个问题已经出现在包括 SO 在内的几个地方,但从来没有一个优雅的答案(甚至也没有一个明确的答案 - 对一个人有用的解决方案对其他人根本不起作用)。

【问题讨论】:

  • 也许做一个 .each() 函数,每次动画完成一个元素,增加一个计数器。当计数器达到动画元素的数量时,运行你的回调函数?
  • @Chris,谢谢,我还没有看到这个问题——太完美了!此外,与下面的@Riley 和@Ross 的答案非常相似。

标签: javascript jquery animation callback


【解决方案1】:

jQuery 在 1.6 版本中引入了promise,比添加计数器要优雅得多。

例子:

// Step 1: Make your animation
$(".buttons").each(function() {
    $(this).fadeIn("fast");
});

// Step 2: Attach a promise to be called once animation is complete
$(".buttons").promise().done(function() {
    // my callback
});

【讨论】:

  • 这应该是答案。
  • 是否会调用 done() 中的回调函数来完成 $('buttons') 中的每个元素,或者当它们全部解决时?
  • @TimeEmit - 只有在所有元素都完成动画后。这与“完成”回调,甚至可以作为选项传入的“完成”承诺回调形成对比。
  • 我同意这是一个优越的解决方案。如果我可以将其指定为接受的答案,我会的。
  • 无需调用 JQuery 选择器两次或 each 函数(在此场景中...调用 jquery 多元素选择器的链式动画将需要它)$(".buttons").fadeIn("fast").promise().done(function { // completion callback }); 就足够了
【解决方案2】:

要将不相关的元素动画收集到单个回调中,您可以这样做:

$.when(
    $someElement.animate(...).promise(),
    $someOtherElement.animate(...).promise()
).done(function() {
    console.log("Both animations complete");
});

【讨论】:

  • 另请注意,您可以将这些承诺收集在一个数组中,然后将applywhen 一起使用,就像我一样:$.when.apply($, animationPromises).done(function() { console.log("done"; } });
  • 没有必要在 $.when 的参数上调用 .promise - 它会自动为您完成。
  • @Alnitak 漂亮的建议,不知道这个! +1
  • @parliament 谢谢,正是我想要的。这是一个 jsfiddle 示例:jsfiddle.net/kw546ybf
  • 这个答案对我有帮助。我在数组中有我的承诺,我使用 jQuery“apply()”函数来调用“when”方法。
【解决方案3】:

@Ross 的答案的替代方案将始终触发最后一个按钮的回调以淡入(可能是也可能不是被告知动画的最后一个按钮):

var buttons = $(".buttons");
var numbuttons = buttons.length;
var i = 0;

buttons.fadeIn('fast', function() {
    i++;
    if(i == numbuttons) {
        //do your callback stuff
    }
});

【讨论】:

  • 这看起来很简单,而且效果很好,但是下面@Underworld 的回答中描述了一个更好的方法。
【解决方案4】:
var $buttons = $('.buttons');

$buttons.each( function (index) { 
    if ( index == $buttons.length - 1 ) {
        $(this).fadeIn('fast',function() {
           // my callback
        });
    } else {
        $(this).fadeIn('fast');
    }
});

未经测试,但这应该只将回调应用于最后一个按钮。

【讨论】:

    【解决方案5】:

    我的解决方案背后的想法是保留一个计数器。每当动画完成时,您只需增加此计数器,因此您可以看到最后一个按钮的时间。记住在一切完成后将计数器设置回零,因为您可能想重复此操作(再次隐藏它们,然后再次显示它们)。

    var $buttons=$('.buttons'),
        button_n=$buttons.length,
        button_counter=0;
    $buttons.fadeIn('fast', function () {
        if (button_counter==button_n-1) {
            alert('It is all done!');
            button_counter=0;
        } else {
            button_counter++;
        }
    });
    

    【讨论】:

      【解决方案6】:
      onClickBtnEdit = function(){
          var $EditDel = $($btnEdit).add($btnDel);
          var btns = $EditDel.size();
      
          $EditDel.fadeOut("def",function(){                   
              btns--;
              if(btns===0){
                  $($btnSave).add($btnCancel).fadeIn("slow");
              }
          });
      };
      

      【讨论】:

        猜你喜欢
        • 2012-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-11
        相关资源
        最近更新 更多