【问题标题】:Jquery - how to delay subsequent animations?Jquery - 如何延迟后续动画?
【发布时间】:2016-08-21 03:28:23
【问题描述】:

好的,我有 8 个 div,我需要一次将它们设置为 1 个动画,这意味着在第 1 和第 2、第 2 和第 3 等之间存在延迟。 起初我将它们全部制作成动画,然后根据 dropdwin,我将只制作几个或几个 div 的动画。

不管我需要我的动画延迟,然后再用另一个 div 运行。

这是我的动画:

function panelIn(labDiv)
        {

            var neww = "100%";
  $(labDiv).delay(600).animate({
    width: neww
  }, 500);

        }

起初我尝试设置一个全局变量并根据它更改延迟,这适用于第一个和第二个 div,但不适用于所有后续:

function panelIn(labDiv)
        {
            if(wasFirst == true)
            {
                wasFirst = !wasFirst;
            var neww = "100%";
  $(labDiv).delay(600).animate({
    width: neww
  }, 500);
            }
            else {
                var neww = "100%";
  $(labDiv).delay(1200).animate({
    width: neww
  }, 500);
            }
        }

我将不得不这样做:

panelIn(div1);
panelIn(div2);
panelIn(div3);
panelIn(div4);

希望避免在它们之间放置一些等待功能。这也很困难,因为 Id 需要将第一个延迟 600,第二个延迟 12000,第三个延迟 1800 等等。我需要它在 panelIn 函数和 1 组延迟内。

如何让我的 div 一次以 1 个动画形式显示?这个可以吗?

【问题讨论】:

标签: javascript jquery html css animation


【解决方案1】:

有 8 个 div

<div class="animateContainer">
  <div class="animateThis">Item 1</div>
  <div class="animateThis">Item 2</div>
  <div class="animateThis">Item 3</div>
  <div class="animateThis">Item 4</div>
  <div class="animateThis">Item 5</div>
  <div class="animateThis">Item 6</div>
  <div class="animateThis">Item 7</div>
  <div class="animateThis">Item 8</div>
</div>

并且您希望能够触发它们中的每一个,但它们会被延迟。第一个延迟600,第二个延迟1200,第三个延迟1800,等等。

var elems = $(".animateThis");

function panelIn(divNumber){
 var neww = "100%";
 $(elems[divNumber]).delay(600 * (divNumber+1)).animate({
    width: neww
  }, 500);

}

panelIn(0);
panelIn(1);
panelIn(2);
panelIn(3);
panelIn(4);
panelIn(5);
panelIn(6);
panelIn(7);

你可以在这里看到这个解决方案https://jsfiddle.net/senordelaflor/h0z87r7f/2/

【讨论】:

    【解决方案2】:

    虽然 Pablo Martinez 的回答向您展示了如何以编程方式修改延迟,但答案是有缺陷的:这样做意味着我们正在超时每个动画(jQuery 可能在内部使用 setTimeout 或类似的),并且由于由于 JavaScript 引擎的工作方式,动画可能会重叠,因为超时不会在指定时间精确执行,只是大约执行。如果您尝试在每个动画的结尾或开头触发事件,您可能会发现事件不会按预期的顺序触发(这是事实,但我不想举个例子来证明这一点)。

    为了保证动画连续触发,你应该使用.animate方法返回的promise来顺序运行动画,这将保证100%的动画连续运行并且永不重叠.

    以下代码未经测试,其技术在this answer 中进行了简要说明(注意,该答案也显示了使用延迟的错误方式),实际上是相同的,但没有延迟时间近似:

    const elems = $('.animateThis')
    
    setTimeout(function() {
      panelIn(0)
      .then(() => panelIn(1)) // arrow function syntax
      .then(() => panelIn(2))
      .then(() => panelIn(3))
      .then(() => panelIn(4))
      .then(() => panelIn(5))
      .then(() => panelIn(6))
      .then(() => panelIn(7))
    }, 500)
    
    function panelIn(divNumber) {
      const neww = '100%'
    
      // return a promise (learn what promises are, they are useful!)
      return $(elems[divNumber]).delay(100).animate({
        width: neww
      }, 500).promise()
    }
    

    如果你在一个支持异步函数的 ES6 JavaScript 环境中,你可以让代码更简洁:

    async function sleep() {
      return new Promise(function(resolve) {
        return setTimeout(resolve, duration)
      })
    }
    
    function panelIn(divNumber) {
      const neww = '100%'
    
      return $(elems[divNumber]).delay(100).animate({
        width: neww
      }, 500).promise()
    }
    
    async function animateDivs() {
      const elems = $('.animateThis')
    
      // Fire each animation sequentially. The `await` keyword makes the engine wait for the given promise to be resolved.
      await sleep(500)
      await panelIn(0)
      await panelIn(1)
      await panelIn(2)
      await panelIn(3)
      await panelIn(4)
      await panelIn(5)
      await panelIn(6)
      await panelIn(7)
    }
    
    animateDivs()
    

    进一步缩短它,使用 sleep 的箭头函数和一个 for 循环:

    const sleep = duration => new Promise(r => setTimeout(r, duration))
    
    function panelIn(divNumber) {
      const neww = '100%'
    
      return $(elems[divNumber]).delay(100).animate({
        width: neww
      }, 500).promise()
    }
    
    async function animateDivs() {
      const elems = $('.animateThis')
    
      await sleep(500)
      for (let i=0; i<8; i++)
        await panelIn(i)
    }
    
    animateDivs()
    

    奖励:如果你想在所有动画完成后做点什么,只需编写另一个异步函数!

    const sleep = duration => new Promise(r => setTimeout(r, duration))
    
    function panelIn(divNumber) {
      const neww = '100%'
    
      return $(elems[divNumber]).delay(100).animate({
        width: neww
      }, 500).promise()
    }
    
    async function animateDivs() {
      const elems = $('.animateThis')
    
      await sleep(500)
      for (let i=0; i<8; i++)
        await panelIn(i)
    }
    
    async function animateDivsThenDoStuff() {
      await animateDivs()
      console.log('All animations complete!')
    }
    
    animateDivsThenDoStuff()
    

    【讨论】:

      【解决方案3】:

      来自我使用 animationend 的评论以及来自另一个答案的 HML 和 CSS 代码

      CSS

      .animate {
        width:100%;
          transition: width .5s linear;
      }
      

      代码

      var i = 1; 
          function animate() { 
      
          var thisone = $(".animate" + i);
          thisone.addClass('animate');
      
          thisone.on('webkitTransitionEnd otransitionend oTransitionEnd msTransitionEnd transitionend',   
              function(e) {
              i++;
              if (i < 9) {
              animate();
              }
            });
          };
      
          animate();
      

      Demo

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-17
        • 2020-08-24
        相关资源
        最近更新 更多