<html>

<body>
  <div>total elapsed time: <span id="total_elapsed"></span></div>
  <div>render count: <span id="render"></span></div>
  <div id="box">
  </div>
</body>

</html>
#box {
  width: 100px;
  height: 100px;
  background: greenyellow;
}
const animate = (cb) => {
  requestAnimationFrame(cb);
};

const makeCb = (target, moveX, duration, fps) => {
  let fpsInterval = 1000 / fps;
  let renderCount = 0;
  let start;
  let then;
  let $totalElapsed = document.getElementById("total_elapsed");
  let $render = document.getElementById("render");

  return function cb(timestamp) {
    if (start === undefined && then === undefined) {
      start = window.performance.now();
      then = window.performance.now();
    }
    const totalElapsed = window.performance.now() - start;
    if (totalElapsed > duration) {
      return;
    }
    $totalElapsed.textContent = totalElapsed;
    const elapsed = timestamp - then;

    if (elapsed >= fpsInterval) {
      // draw
      then = timestamp - (elapsed % fpsInterval);
      renderCount++;
      $render.textContent = renderCount;
      const transformStyle = target.style.transform;
      const translateX = transformStyle.replace(/[^\d.]/g, "");
      target.style.transform = `translateX(${+translateX + moveX}px)`;
    }
    requestAnimationFrame(cb);
  };
};

const $box = document.getElementById("box");
animate(makeCb($box, 2, 1000, 30));

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.