You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Javascript requestAnimationFrame游戏循环运行无画面显示问题如何修复

问题根因与修复方案

错误原因

你的写法存在核心逻辑错误:setTimeout(window.requestAnimationFrame(eachFrame), 1000 / fps) 中,window.requestAnimationFrame(eachFrame) 会被立即执行,而非作为回调延迟触发。这就导致你的渲染循环会以远高于预期的速度疯狂执行:清屏→更新位置→渲染→立刻触发下一次循环清屏,渲染出的内容存在时间过短,人眼完全无法捕捉,最终表现就是屏幕全白。

另外你混淆了API的用法:requestAnimationFrame 本身会跟随浏览器的刷新频率(通常为60次/秒)调度回调,不需要额外嵌套setTimeout,这种套写本身就是错误用法。

修复方案

方案1:默认使用浏览器原生帧率(推荐,无闪烁)

直接移除多余的setTimeout包裹即可,原生requestAnimationFrame的调度机制本身就能避免setInterval导致的闪烁问题:

function eachFrame(){
    ctx.clearRect(0,0,canvas.width,canvas.height);
    player.motion();
    player.render();
    window.requestAnimationFrame(eachFrame);
};

window.requestAnimationFrame(eachFrame);

方案2:需要自定义固定帧率

如果你确实需要限制渲染帧率,可通过时间差控制帧执行时机:

let lastRenderTime = 0;
const expectedFps = 30; // 替换为你需要的帧率
const frameInterval = 1000 / expectedFps;

function eachFrame(currentTime){
    // 距离上一次渲染的间隔达到预期帧间隔时才执行渲染
    if (currentTime - lastRenderTime >= frameInterval) {
        lastRenderTime = currentTime - ((currentTime - lastRenderTime) % frameInterval);
        ctx.clearRect(0,0,canvas.width,canvas.height);
        player.motion();
        player.render();
    }
    window.requestAnimationFrame(eachFrame);
};

window.requestAnimationFrame(eachFrame);

补充说明

你注释ctx.clearRect后能看到移动轨迹,是因为没有清屏操作的情况下,每次渲染的内容都会叠加保留在画布上,就算循环执行速度再快,内容也会累计,因此可以看到移动效果,但也会产生轨迹残留。

内容的提问来源于stack exchange,提问作者Stephen Witwick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 21:54:06