【问题标题】:JS/CSS : transition not occurring unless within a setTimeoutJS/CSS:除非在 setTimeout 内,否则不会发生转换
【发布时间】:2021-04-14 08:59:45
【问题描述】:

如果我创建一个循环来动态添加在 transform 上进行转换的元素,为什么这个示例不起作用:

function changeSize() {
   for (let x = 0; x < 99; x++) {
      let el = document.createElement('div');
      el.style.translate = 'transformX(0px)';

      el.style.translate = 'transformX(150px)';
      el.style.transition = 'all 2s ease';
      
      let body = document.body;
      body.appendChild(el);
   }
}

但这确实有效,只要我添加一个非常小的超时:

function changeSize() {
   for (let x = 0; x < 99; x++) {
      let el = document.createElement('div');
      el.style.translate = 'transformX(0px)';

      // now it will transition 
      setTimeout(() => {
         el.style.translate = 'transformX(150px)';
         el.style.transition = 'all 2s ease';
      }, 50)

      let body = document.body;
      body.appendChild(el);
   }
}

【问题讨论】:

    标签: javascript css


    【解决方案1】:

    当您设置转换然后在同一个线程中重置它时,它只是更改值并采用后面的值。 setTimeout 将所有内容带到浏览器级别(不是javascript级别,因为js是单线程的)的不同线程,导致在值更改时发生动画。然而,像这样的 javascript 在不同的浏览器中通常是不可预测的 - 而是使用 css 来进行这样的转换。

    function changeSize() {
      for (let x = 0; x < 99; x++) {
        let el = document.createElement("div");
        el.innerHTML = "hi"
        el.style.transition = "all 2s ease";
        setTimeout(function() {
          el.classList.add("transition");
        }, 1)  /*Brings everything to a different thread.
    When the browser sees this, it's like - oh look, a setTimeout, I need to move this to a time thread,
    so when the time completes I can execute the function! So it does that.
    Since the time is very little, it completes within a short amount of time.
    The browser sees this, and realizes that it needs to execute the function - so it removes it from it's
    execution stack and executes it.
    When executing, it sees that the thread is asking for a classList change for the element el.
    So, it changes the class, triggering any css with it (in this case the transform css).
    Since the element has a transition, it appropriately transitions during the translation.
    */
        document.body.appendChild(el);
      }
    }
    changeSize()
    .transition {
      transform: translate(100px, 0);
    }

    请注意 setTimeout 的值 1,因为某些浏览器不会等待值 0(如将其移至单独的堆栈)。

    现在,您可能想知道,为什么这是“不可预测的”?嗯,这是因为在这么短的超时时间内,它可以与主线程中的其他代码一起执行。如果您在主线程中有更改元素 css 的代码,那么浏览器将发生冲突,并且会根据首先执行的内容执行不同的操作。但是,如果您使用一个类,然后稍后自己更改元素的样式,则样式将覆盖该类,因为它是直接应用于元素而不是通过类的方式。

    【讨论】:

    • 谢谢。在您的代码中,为什么在 setTimeout 之前添加一行来给它一个起点不起作用,例如:el.style.transform = translate(0px, 0px) 然后在它下面的 setTimeout 中,添加给它一个不同翻译的类。
    • 那是因为当你这样做时,el 元素本身会被设置样式,这会覆盖类。这正是通过允许以后的代码覆盖它来防止以后代码中出现 css 问题的确切方法,在这种情况下,这就是它的作用:)。
    • facepalms self 没注意到,谢谢!!
    猜你喜欢
    • 1970-01-01
    • 2019-06-08
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    • 1970-01-01
    • 2013-12-16
    • 2022-11-07
    • 2022-12-23
    相关资源
    最近更新 更多