【问题标题】:Chrome on OSX: CSS transitions applied immediately to second clone of div [duplicate]OSX 上的 Chrome:CSS 过渡立即应用于 div 的第二个克隆 [重复]
【发布时间】:2021-02-08 04:37:14
【问题描述】:

我想做以下事情:创建一个 div (#test),然后多次克隆该 div,每次克隆它时都会通过 javascript 添加一个 css 转换。第一次一切正常,但如果我尝试第二次克隆并应用 css 过渡,则过渡不起作用。

在此示例 (https://jsfiddle.net/9uL1qt6n/13/) 中,红色方块按预期移动,但绿色方块不移动,并立即出现在过渡结束时。

这是我正在使用的 javascript 代码:

function move(color){
  let clone=document.getElementById("test").cloneNode(true);
  clone.id=color;
  clone.style.display="block";
  clone.style.backgroundColor=color;
  document.getElementById("main").prepend(clone);
  setTimeout(function(){
      clone.style.left="500px";
  },0)
}

setTimeout(function(){move("red")},500);
setTimeout(function(){move("green")},750);

我希望红色方块在 0.5 秒时以 left=0px 开始并向右移动,然后是在 0.75 秒时以 left=0px 开始并向右移动的绿色方块。我看到的是一个红色方块,在 0.5 秒处以 left=0px 开始并向右移动,然后是一个在 0.75 秒处以 left=500px 开始并且不移动的绿色方块。

编辑:这似乎可以在 Mac 上的 Safari 以及 iOS 上的 Safari 和 Chrome 上正常工作。以上建议的行为仅出现在 Mac 上的 Chrome 上。

【问题讨论】:

    标签: javascript css google-chrome css-transitions clonenode


    【解决方案1】:

    这是因为setTimeout(/**/, 0) 不保证回调将在后续帧上执行。这可能(取决于浏览器实现和计算机速度)导致样式应用在与插入 DOM 的节点相同的帧上。

    理论上,您应该改用requestAnimationFrame,这正好适用于这种情况。

    但是,在您链接的小提琴中,只有当我将 requestAnimationFrame 翻倍时它才有效,这是难以察觉但仍然不可取的... IDK 如果它是 JSFiddle 的侥幸或什么...

    function move(color){
      let clone=document.getElementById("test").cloneNode(true);
      clone.id=color;
      clone.style.display="block";
      clone.style.backgroundColor=color;
      document.getElementById("main").prepend(clone);
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
            clone.style.left="500px";
        })
      })
    }
    

    这是一个 sn-p:我在 SO sn-p 中找到了同样的东西

    function move(color) {
      let clone = document.getElementById("test").cloneNode(true);
      clone.id = color;
      clone.style.display = "block";
      clone.style.backgroundColor = color;
      document.getElementById("main").prepend(clone);
      requestAnimationFrame(() => {
        requestAnimationFrame(() => {
          clone.style.left = "500px";
        })
      })
    }
    
    
    setTimeout(() => move("red"), 500);
    setTimeout(() => move("green"), 750);
    #main {
      display: block;
      width: 100vw;
      height: 100vh;
      background-color: blue;
    }
    
    .test {
      position: absolute;
      display: none;
      width: 100px;
      height: 100px;
      background-color: red;
      transition: left 1s ease;
      transform: scale(1);
      left: 0px;
    }
    <div id="main"></div>
    <div id="test" class="test"></div>

    【讨论】:

    • requestAnimationFrame before 触发下一次绘制,所以如果中间没有触发回流,它在这里并没有真正的帮助。您可以在 raf 回调中等待 0 超时,但无需等待任何内容,如链接的欺骗中所述。
    • @Kaiido 该链接没有解释它 IMO,因为这里的 .prepend 应该已经触发了重新计算(在当前帧期间),并且 RAF 不应该在当前帧上执行。我错过了什么?
    • 在您链接的线程之后,这里有一个完整的解释,它在删除 display: nonestackoverflow.com/questions/54344996/… 后使用单个 RAF 触发动画。
    • 是的,它确实解释了它,我承认有几个链接。 .prepend 不应该触发回流,继续跟踪链接直到 this answer 以更好地理解什么是回流,以及让每个 DOM 操作(如预先触发)是多么可怕。另外,从您提供的链接中,我说(是的,我确实写了所有这些答案)您甚至不需要 rAF,您可以同步完成所有操作,就像在标记为欺骗中公开的那样。 jsfiddle.net/j9dotnyc
    猜你喜欢
    • 2016-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    相关资源
    最近更新 更多