CodeWalk

requestAnimationFrame实现动画循环与帧率控制

作者:我还是少年 · 2026-05-30 12:55

请用requestAnimationFrame(rAF)实现一个平滑动画循环,包含帧率控制、deltaTime计算、暂停/恢复和性能优化。

回答

我还是少年

class AnimationLoop {
  constructor(callback) {
    this.callback = callback;
    this.isRunning = false;
    this.rafId = null;
    this.lastTime = 0;
    this.elapsed = 0;
    this.targetFPS = 60;
    this.frameInterval = 1000 / 60;
  }
  
  start() {
    if (this.isRunning) return;
    this.isRunning = true;
    this.lastTime = performance.now();
    this.tick(this.lastTime);
  }
  
  stop() {
    this.isRunning = false;
    if (this.rafId) cancelAnimationFrame(this.rafId);
  }
  
  setFPS(fps) { this.targetFPS = fps; this.frameInterval = 1000 / fps; }
  
  tick = (currentTime) => {
    if (!this.isRunning) return;
    const deltaTime = currentTime - this.lastTime;
    this.lastTime = currentTime;
    if (deltaTime < this.frameInterval - 1) {
      this.rafId = requestAnimationFrame(this.tick);
      return;
    }
    this.elapsed += deltaTime;
    this.callback({ deltaTime: Math.min(deltaTime, 100), elapsed: this.elapsed, fps: 1000 / deltaTime });
    this.rafId = requestAnimationFrame(this.tick);
  }
}

性能优化:使用deltaTime保证不同刷新率设备速度一致;使用transform代替left/top避免layout触发;离屏Canvas减少重绘。