【问题标题】:jQuery: Animations occur simultaneously instead of back-to-back with .each() iterationjQuery:动画同时发生而不是与.each()迭代背靠背
【发布时间】:2018-05-07 17:29:10
【问题描述】:

我正在遍历“.mini”类对象的数组。对于每个对象,每个对象将在移动(调用 go 函数)之前等待 500 毫秒(setTimeout 函数)。例如,

function iterate() {
    $(".mini").each(function(index)
    {
        var element = $(this);
        setTimeout(function() {go(element)}, 500);
    });
}

function go(element) {
    element.animate({left: "500px"},200);
}

但是,每个元素的动画都是同时发生的(所有 32 个 .mini 对象同时移动),而不是一个接一个地移动。如何让第一个在开始时间 500 秒后开始移动,第二个在开始时间 1000 秒后开始移动,等等?

【问题讨论】:

  • “[...] 500 秒后 [...]”,我想您的意思是“毫秒”,对吗?

标签: javascript jquery animation methods each


【解决方案1】:

您应该将500index + 1 相乘,以便第一个发生在500ms,第二个发生在1000ms,等等。

setTimeout(function() {go(element)}, 500 * (index + 1));

现在,您遍历所有这些,并告诉他们每个人500ms from now, do this。所以,500ms 从现在开始,他们每个人都会这样做。

【讨论】:

  • 超级简单有效。其他答案试图确保正确的链接时间,但我怀疑人眼不会注意到一两毫秒的重叠/断开。
  • 我认为给出的问题是“如何让第一个在开始时间 500 秒后开始移动,第二个在开始时间 1000 秒后开始移动,等等?” - 其他的实际上更有可能没有在适当的时间开始(如果每个人都用1ms 来做它的逻辑并安排下一个,那么在完成 1000 个项目之后,我们会延迟一秒)。
  • 但问题的标题是要求它们“背靠背”发生;暗示关系。你是对的,可能会有逻辑开销,但它们会一个接一个地发生,而不是允许重叠。
  • 是的,他真正想要的是哪一个还有些模糊。最后这并不重要,因为动画是 200 毫秒,并且之间的延迟是 500
  • 我现在真的很困惑。是500-animation(200)-500-animation(200)-500-... 还是500-animation(200)-300-animation(200)-300-...
【解决方案2】:

使用Promises 和reduce。等到上一个动画结束后再开始下一个动画。

如果您想等待开始初始动画,请将整个链接包装在 setTimeout() 中。

Array.from(document.querySelectorAll("ul > li")).reduce((prev, curr) => {
  return prev.then(function() {
    return new Promise((resolve, reject) => {
      $(curr).animate({
        opacity: 0.2
      }, 1000, function() {
        resolve();
      });
    });
  });
}, Promise.resolve());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li>Hello</li>
  <li>Hello</li>
  <li>Hello</li>
  <li>Hello</li>
  <li>Hello</li>
  <li>Hello</li>
</ul>

【讨论】:

    【解决方案3】:

    它们都是同时发生的,因为所有setTimeouts 都在each 内部调用,循环元素列表不需要很长时间(仅几毫秒)。如果你想链接它们,那么使用jQuery#animatecomplete 回调来发出下一个动画开始的信号:

    function iterate() {
        var $list = $(".mini"),                                // get the whole list of elements
            i = 0;                                             // i is the index of the currently animated element from list
    
        function next() {                                      // the function that when called will get the current element from list (if exists) and starts that element's animation
            if(i < $list.length) {                             // if there is still un-animated elements in $list
                setTimeout(function() {                        // animate the current element
                    go($list.eq(i), next);                     // specify that next will be called when the current element's animation is done
                }, 500);
                i++;                                           // increment i of course
            }
        }
    
        next();                                                // call next to start the magic
    }
    
    function go(element, complete) {                           // go will take an element to be animated, and a function that will be called when that animation is done
        element.animate({left: "500px"}, 200, complete);       // simply call animate with that additional function (see jQuery#animate docs)
    }
    

    【讨论】:

    • list.eq(0) 正确吗?我认为您缺少$,它应该使用i,对吗?所以$list.eq(i) 也许?
    • 很好的解决方案!谢谢!
    猜你喜欢
    • 2018-08-18
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 2011-06-09
    • 2011-07-19
    • 2012-09-22
    • 2010-12-14
    • 2012-10-17
    相关资源
    最近更新 更多