【问题标题】:Animate complete infinite loop in jQuery在 jQuery 中动画完整的无限循环
【发布时间】:2015-09-24 02:18:41
【问题描述】:

我正在尝试制作一个又一个动画。

我的做法是这样的:

$(class).animate(
    {something},
    {
        duration: 1000,
        complete: function(){
                      $(class).animate(
                          {something},
                          {
                              duration: 1000,
                              complete:  function(){
                              // More to animate when previous animation is done
                          }
                  });
    }
});

到目前为止,这工作得很好。我的问题如下:

为了触发这个动画链,我使用了一个元素的点击。当您单击该元素时,会出现一个变量“ongoing”,该变量为真,因此无法重新单击该元素,因为尚未到达动画的结尾。

这个动画链中最深的动画如下。

complete: function(){
    $(few divs).each(function(){
        $(this).delay(delay).animate(
            {"opacity": 1},
            {
                duration:2000,
                complete: function(){
                      console.log(i + " finished"); //
                      if(i == 2){ // 3 divs
                          ongoing = false; // All the animations are finished, allowed to reclick
                      }
                }
                delay += 2000;
            });
}

问题在于它显示了 3 次 0,1,2。

0 finished
1 finished
2 finished
0 finished
1 finished
2 finished
0 finished
1 finished
2 finished

然后我尝试了这个:

complete: function(){
    selected = text;

    $(few divs).each(function(i){
        $(this).delay(delay).animate({"opacity": 1}, 2000);
        delay += 2000;
    }).promise().done(function(){ // All each's are finished
        ongoing = false;
        console.log("finished");
    });
}

在这个例子中,还有一个无限循环,“完成”...

我的代码到底发生了什么,为什么它不起作用?

【问题讨论】:

  • 您是否尝试过递归调用而不是硬编码每个级别?此外,为什么不将函数作为回调而不是在完成事件中,如jQuery animate page 页面下方所示
  • 不,我没试过,但我会的。你知道回调函数和函数animate的完整参数有什么区别吗?
  • 据我所知,实际上似乎没有任何区别。不过,我从未见过有人将函数放在 Complete 事件中,而不仅仅是将其作为常规回调。

标签: jquery jquery-animate promise each


【解决方案1】:

}).promise().done(function(){ // all each's are finished

这是错误的 - 它总是立即执行。

您需要将 animate() 的延迟对象推送到数组中;考虑下面的例子。

var promises = [];
$(few divs).each(function(i){ 
    promises.push(
        $(this)
            .delay(i * 2000)
            .animate({
                "opacity": 1
            }, 2000)
    );
})
$.when.apply($, promises).done(function() {});

【讨论】:

  • 您的apply 缺少第一个参数thisArg
  • @oxynad 你不能只是说某事不起作用。至少发布代码。如果你使用console.log(),为什么不把它放在大量的位置,这样你就可以清楚地看到事件的执行顺序?我提供的代码sn-p只会执行一次done()函数,除非整个sn-p被多次调用。
  • 我在 function() 中添加了一个 console.log,由于某种原因,它在动画完成后大约 6 秒显示 3“完成”。这是为什么?我会再测试一些
  • @oxynad each() 内的这些动画的调用延迟增加。 done() 函数将在最后一个动画完成后立即执行。您可以将一些回调函数添加到您的 animate() 方法中,以准确查看它们各自完成的时间。
【解决方案2】:

“增加延迟”方法实际上给出了一组单独的动画,每个动画都有一个预测的开始时间,以提供端到端的序列效果 - 可能会出现时间错误。

更好的方法是通过构建.then() 链来创建具有保证时序的真正动画序列。

complete:  function() {
    var promise = $.when();
    $(few divs).each(function() {
        promise = promise.then(function() {
            return $(this).animate({'opacity': 1}, 2000).promise();
        });
    });
    promise.done(function() { // All animates are complete
        ongoing = false;
        console.log('finished');
    });
}

或者,使用 Array 的 .reduce() 方法稍微更紧凑:

complete: function() {
    $(few divs).get().reduce(function(promise, el) {
        return promise.then(function() {
            return $(el).animate({'opacity': 1}, 2000).promise();
        });
    }, $.when()).done(function() { // All animates are complete
        ongoing = false;
        console.log('finished');
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多