如何运行 requestAnimationFrame 动画一段时间?

McD*_*erp 1 javascript animation requestanimationframe

我有以下功能,通过每次“勾选”调整元素的样式,将某些元素“向上”滚动到视图之外:

const incr = 1;
let moved = 0;

function changeHeight( children, duration, setTop) {
  // duration = 1500
  const height = children.clientHeight; // in this case, 166px

  let moved = 0; 
  const slideUp = function (timestamp) {
    // we're done if the amount moved is larger than height
    if ( moved < height ) { 
      children.style.top = `${ setTop( moved, height ) }px`;
      moved = moved + incr // move by some amount

      requestAnimationFrame(slideUp) 

    } else {
      // reset
      moved = 0;
    }
  };

  // start sliding
  slideUp();
}
Run Code Online (Sandbox Code Playgroud)

如果requestAnimationFrame大约每 16 毫秒左右触发一次,我想用它来duration指示动画将运行多长时间,所以公式似乎是height * 16.5 / duration

我很困惑requestAnimationFrame- 为什么每次滴答的时间不是恒定的?我想使用timestamp它生成的requestAnimationFrame,但前几个周期比平均值 ~16.5 长得

16.5 在不同的机器或屏幕上看起来会有所不同吗?

如何使高度变化精确地按照指定的时间进行?

Kai*_*ido 5

你想要的叫做增量时间。公式为Math.min((now - start) / duration, 1) * final_amount

使用这个增量时间,您不需要关心间隔触发的频率,每个步骤都会呈现“它应该在的位置”。

至于你的问题,

为什么每次滴答的时间不是恒定的

当然是因为浏览器在第一个帧中有很多事情要做,而无法在 16.7 毫秒帧中完成所有事情。因此,它会将您的回调移到稍后执行,如果压力太大,甚至可能会跳帧。

16.5 在不同的机器或屏幕上看起来会有所不同吗?

是的,requestAnimationFrame基本上会尝试遵循显示器的刷新率。因此,在 60Hz 显示器上,每帧确实有 16.7 毫秒,但在 120Hz 显示器上,每帧只有一半。

如何使高度变化精确地按照指定的时间进行?

使用增量时间:

const elem = document.querySelector("div");
let moved = 0;
changeHeight(elem, 200, 5000);

function changeHeight(elem, height, duration) {
  const start = performance.now();
  const step = function () {
    const now = performance.now();
    const delta = Math.min((now - start) / duration, 1);
    elem.style.height = (delta * height) + "px";
    if (delta < 1) {
      requestAnimationFrame(step);
    }
  };
  step();
}
Run Code Online (Sandbox Code Playgroud)
div { width: 50px; background: green; }
Run Code Online (Sandbox Code Playgroud)
<div></div>
Run Code Online (Sandbox Code Playgroud)