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

为什么Canvas动画中rectX、rectY全局变量会被赋值为NaN?已解决

Canvas 游戏循环坐标变为NaN问题解答

问题根因

核心问题出在首次调用gameLoop函数的逻辑上:

  • 初始代码直接执行无参调用gameLoop(),此时函数接收的timeStamp参数为undefined
  • 执行secondsPassed = (timeStamp - oldTimeStamp) / 1000运算时,undefined - 0的结果为NaN
  • 后续update函数中movingSpeed * secondsPassed的结果仍为NaN,数值变量与NaN累加后会被覆盖为NaN
  • 因为NaN属于JavaScript合法的数值运算结果,所以控制台不会抛出显式报错

如果你检测到rectX曾被识别为字符串,需要额外检查其他业务逻辑中是否存在意外给坐标变量赋值字符串的操作,这类隐式类型转换也会导致累加结果异常。

修正逻辑说明

你提供的修正后代码解决了核心的参数传递问题:

  1. 去掉了直接无参调用gameLoop()的写法,改为通过window.requestAnimationFrame触发首次执行:requestAnimationFrame会自动给回调函数传入高精度时间戳参数,保证首次计算的secondsPassed是合法数值
  2. 后续循环触发gameLoop时,也通过匿名函数包裹确保timeStamp参数能正确传递,避免参数丢失

原始问题代码

const canvas = document.querySelector('#canvas')
const context = canvas.getContext('2d')
let rectX = 0 ;
let rectY = 0;
let secondsPassed = 0;
let timeStamp = 0
let oldTimeStamp = 0;
let movingSpeed = 50;
gameLoop() // 错误点:无参调用,timeStamp为undefined
function draw() {
    context.fillStyle = 'red';
    context.fillRect(rectX, rectY, 150, 100);
}

function gameLoop(timeStamp) {
    // Calculate how much time has passed
    secondsPassed = (timeStamp - oldTimeStamp) / 1000;
    oldTimeStamp = timeStamp;
    update(secondsPassed);
    draw();

    window.requestAnimationFrame(gameLoop);
}

function update(secondsPassed) {
    rectX += (movingSpeed * secondsPassed);
    rectY += (movingSpeed * secondsPassed);
}

修正后代码

const canvas = document.querySelector('#canvas')
const context = canvas.getContext('2d')
let rectX = 0;
let rectY = 0;
let secondsPassed = 0;
let oldTimeStamp = 0;
let timeStamp = 0
let movingSpeed = 50;
let timePassed = 0
function draw() {
    context.fillStyle = 'red';
    context.fillRect(rectX, rectY, 150, 100);
}

function gameLoop(timeStamp) {
    // Calculate how much time has passed
    secondsPassed = (timeStamp - oldTimeStamp) / 1000;
    oldTimeStamp = timeStamp;

    // Pass the time to the update
    update(secondsPassed);
    draw();

    window.requestAnimationFrame(function(timeStamp){gameLoop(timeStamp)});
}

function update(secondsPassed) {
    // Use time to calculate new position
    rectX += (movingSpeed * secondsPassed);
    rectY += (movingSpeed * secondsPassed);
}
// 正确:通过requestAnimationFrame传参触发首次调用
window.requestAnimationFrame(function(timeStamp){gameLoop(timeStamp)});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:36:01