Chrome on OSX:CSS过渡立即应用于div的第二个克隆

问题描述

我想执行以下操作:创建一个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);

我期望红色正方形从.5s处的左= 0px开始向右移动,然后是绿色正方形,从.75s处的left = 0px开始向右移动。我看到的是一个红色正方形,从.5s处的left = 0px开始向右移动,然后一个绿色正方形,从.75s的left = 500px开始并且不移动。

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

解决方法

这是因为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";
    })
  })
}

这是一个代码段:我在SO代码段中找到了相同的内容

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>