requestAnimationFrame 似乎无效

requestAnimationFrame appears to be invalid

我最近看了 Jake Archibald 的演讲。他在演讲中举了一个例子,他说两次使用 requestAnimationFrame 来延迟应用 CSS 样式来执行 CSS 动画。

https://youtu.be/cCOL7MC4Pl0?t=1337

我重现了这个例子来测试它,但没有运气:

盒子会直接移动到500px的位置,而不是从1000px移动到500px。

有人提出了 Jake Archibald 的解决方案。使用两层嵌套的 requestAnimationFrame

但它似乎对我不起作用。为什么?

这是应该的代码片段:

const box = document.getElementById("box");
box.addEventListener("click", ()=>{
  box.style.transform = 'translateX(500px)';
  box.style.transition = 'transform 1s ease-out';
  requestAnimationFrame(()=>{
    requestAnimationFrame(()=>{
        box.style.transform = 'translateX(250px)';
    });
  });
});
#box {
  background-color: salmon;
  height: 100px;
  width: 100px;
  cursor: pointer;
}
<div id="box">box</div>

是这样的吗?

const box = document.getElementById("box");
box.addEventListener("click", ()=>{
  box.style.transform = 'translateX(500px)';
  requestAnimationFrame(()=>{
    box.style.transition = 'transform 1s ease-out';
    requestAnimationFrame(()=>{
        box.style.transform = 'translateX(250px)';
    });
  });
});
#box {
  background-color: salmon;
  height: 100px;
  width: 100px;
  cursor: pointer;
}
<div id="box">box</div>

我真的很讨厌视频所以我没有完全检查它,但肯定他们在调用 javascript.

之前已经翻译了 #box 元素

如果他们不这样做,那么它实际上会在一帧内执行从 translateX(0)translateX(1000px) 的过渡,并且在从任何地方(可能离左开始不远)过渡到translateX(250px).

因此,为了修复,您可以在 CSS 中设置初始 translateX 值。

const box = document.getElementById("box");
box.addEventListener("click", ()=>{
  box.style.transform = 'translateX(500px)';
  box.style.transition = 'transform 1s ease-out';
  requestAnimationFrame(()=>{
    requestAnimationFrame(()=>{
        box.style.transform = 'translateX(250px)';
    });
  });
});
#box {
  background-color: salmon;
  height: 100px;
  width: 100px;
  cursor: pointer;
  transform: translateX(1000px);
}
You have to scroll to the right now.
<div id="box">box</div>

现在,您真的不应该使用双重 requestAnimationFrame hack。相反 (即强制回流)。

const box = document.getElementById("box");
box.addEventListener("click", ()=>{
  box.style.transform = 'translateX(500px)';

  box.offsetWidth; // force reflow so our box is translated to initial position
  box.style.transition = 'transform 1s ease-out';
  box.style.transform = 'translateX(250px)';
});
#box {
  background-color: salmon;
  height: 100px;
  width: 100px;
  cursor: pointer;
}
<div id="box">box</div>