有没有办法为 high/low 不在 60hz 的帧率监视器设置 rAF 的 FPS?

Is there a way to set FPS for rAF for high/low frame rate monitors not on 60hz?

所以我有一台 120hz 显示器和一台 60hz 显示器。如果我 运行 我的游戏在第一个显示器上,它 运行 非常快,但是当我 运行 在第二个显示器上时,它会变慢。而且我知道那里也有很多 30hz 显示器,速度会更慢(还有一点点 240hz 显示器,速度快如闪电)。有什么方法可以将游戏的帧率锁定在 60fps(这是最常见的),这样问题就不会发生了?

不,requestAnimationFrame 应该在下一次屏幕刷新之前触发,这使其与屏幕刷新率相关联。

你需要的是 delta-time.

不是在每个滴答时按静态值增加对象位置,而是测量自上次滴答以来的时间,并根据经过的时间和预设持续时间更新您的值。

这样,无论显示器的刷新率如何,或者即使页面受到计算机等的限制,您的动画对象也会以相同的速度在任何地方行走给定的距离。

这里是一个例子,显示即使我们“暂停”动画,当我们“恢复”它时,对象也会在没有暂停的情况下应该在的位置。

const it = document.getElementById( "it" );
const checkbox = document.querySelector( "input" );
const maxLeft = window.innerWidth - 50;
const duration = 2000; // time to traverse the screen (ms)
const start = performance.now();

function anim( now ) {

  // 'now' passed by rAF is the time the last VSync event has been sent by the monitor
  // it may not be the real "now" time, for this one could use
  // performance.now() instead
  const delta = ((now - start) % duration) / duration;
  // determine if we should go to left or to right
  const direction = Math.sign( ((now - start) % (duration * 2)) - duration );

  let position;
  if( direction < 0 ) {
    position = delta * maxLeft;
  }
  else {
    position = maxLeft - (delta * maxLeft);
  }
  it.style.transform = `translateX(${ position }px)`;
  if( checkbox.checked ) {
    requestAnimationFrame( anim );  
  }
}

requestAnimationFrame( anim );
checkbox.oninput = anim;
#it {
    width: 50px;
    height: 50px;
    background: red;
    border-radius: 50%;
    position: fixed;
    top: 50px;
    will-change: transform;
}
<div id="it"></div>
<label>pause/resume<input type="checkbox" checked></label>

Kaiido 的方法非常适合简单的动画和游戏,但如果您需要更复杂的功能,还可以采用其他一些方法。

假设某种操作每秒需要发生 n 次;我们称之为滴答声。一种方法是让 requestAnimationFrame 以及 setInterval 用于可能需要在帧之间发生的任务。例如:

var tick_rate = 50; // This is the ideal number of ticks per second

function draw_frame(now) {
    // This code only handles the graphics

    requestAnimationFrame(now);
}

function run_tick() {
    // This is where you handle things that don't happen "smoothly"
    //   (i.e., can't be calculated at a varying rate)
}

requestAnimationFrame(now);
setInterval(run_tick, 1000 / tick_rate);

对于某些事情,这绝对不是理想的方法,但在以已知时间间隔发生特定事件或计算更容易的情况下,它可以使事情变得更容易。