requestAnimationFrame 的时间戳在各种/更高刷新率下有什么不同?

What's different with requestAnimationFrame's timestamp at various / higher refresh rates?

所以我有一个 运行 循环:

var FRAME_TIME = 1000 / 60;
var lastTime = 0;
var fpsTime = 0;
var fps = 0;

function mainLoop(timestamp) {
    if (timestamp - lastTime >= FRAME_TIME) {
        fps++;
        lastTime = timestamp;
    }

    if (timestamp - fpsTime >= 1000) {
        console.log(fps);
        fps = 0;
        fpsTime = timestamp;
    }
    requestAnimationFrame(mainLoop);
}

现在,当 运行 监视器在 60 刷新时,我会按预期在控制台中打印“60”。但是,当 运行 在 144 处刷新时,我得到“48”= 1/3 的刷新。

为什么?时间就是时间,对吧...?

所以我认为主要问题归结为这些行。

if (timestamp - lastTime >= FRAME_TIME) {
    fps++;
    lastTime = timestamp;
}

也就是说,如果我们当前的帧时间(时间戳 - 最后时间)超过(或等于)'ideal' 帧的时间(1000 毫秒/60 [144]),那么我们计算它,否则不算。

如果这个函数每帧调用(一次且仅一次),那么你不需要 if 语句,你可以简单地每帧做 "fps++",因为它会被 1 秒重置柜台.

if (timestamp - lastTime >= FRAME_TIME) fps++;不行。这意味着它不会计算每一帧 - 它会在 FRAME_TIME 过去时计算。在 144 fps 时,这意味着在计算下一帧 21 ms 之前有两帧(7 ms 和 14 ms),即在预期的 FRAME_TIME 60 fps - 17 ms 之后。这归结为仅计算每三帧一次 - 正是您所体验到的。

要修复它,请在每次调用时执行 fps++

var fpsTime = 0;
var fps = 0;

function mainLoop(timestamp) {
    fps++;
    if (timestamp - fpsTime >= 1000) {
        console.log(fps);
        fps = 0;
        fpsTime = timestamp;
    }
    requestAnimationFrame(mainLoop);
}
mainLoop(performance.now());