requestAnimationFrame似乎无效

时间:2020-03-06 07:15:26

标签: javascript html css event-loop requestanimationframe

我最近看了杰克·阿奇博尔德的演讲。他在演讲中举了一个例子,他说要两次使用requestAnimationFrame来延迟应用CSS样式来执行CSS动画。

请参见https://youtu.be/cCOL7MC4Pl0?t=1337

我转载了示例进行测试,但是没有运气:

该框将直接移动到500px的位置,而不是从1000px移到500px。

提出了杰克·阿奇博尔德的解决方案。使用两层嵌套的requestAnimationFrame

image

但是它似乎不适用于我。为什么?

这是应该应该起作用但不能起作用的代码段:

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>

2 个答案:

答案 0 :(得分:2)

像这样吗?

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>

答案 1 :(得分:0)

我真的很讨厌视频,所以我没有完全检查它,但是可以肯定的是,他们在调用该JavaScript之前已经翻译了#box元素。

如果没有,那么它将在一帧内实际执行从translateX(0)translateX(1000px)的过渡,并且在从任何位置(可能从左开始不远处)过渡到{{ 1}}。

因此,要解决此问题,可以在CSS中设置初始translateX(250px)值。

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);
}

现在,您实际上不应该使用双重requestAnimationFrame hack。而是identify the problem and use a proper fix(即强制重排)。

You have to scroll to the right now.
<div id="box">box</div>
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;
}