【问题标题】:Why does the global variable gets value NaN? Solved Thank you Everyone为什么全局变量的值是 NaN?解决了 谢谢大家
【发布时间】:2021-11-19 19:43:48
【问题描述】:
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()
    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);
    }

rectX 和 rectY 最初有一个数字值,movingSpeed 也有一个数字值, secondsPassed 也是如此。我的问题是为什么函数“更新”将 NaN 赋予变量 rectX 和 rectY ?控制台中没有显示错误。我尝试记录并使用 typeof 来检查每个变量是否都有一个类型编号的值,我注意到 rectX 曾经被认为是一个字符串,我试图解析 rectX 但它仍然给了我 NaN。通常,我们使用 timeStamp 返回一个可以帮助我们计算 fps 的值。在这种情况下,我使用 timeStamp 来查看在运行函数 gameLoop 之前已经过去了多少秒。我这样做是因为决定游戏速度的不再是帧速率(和硬件),而是时间。

更新:已解决,感谢 @epascarello、@James 和 @Kaiido。有更新的代码给你们:

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);
        
        
    }
    window.requestAnimationFrame(function(timeStamp){gameLoop(timeStamp)});

【问题讨论】:

  • 添加console.log()看看什么是NaN
  • rectXrextY 最初是 undefined
  • 因为你从不传入timeStamp 看看gameLoop() function gameLoop(timeStamp) { 带有变量的简单console.log() 会让你看到这一点。
  • timeStamp 应该是什么?当前未定义,这将使 oldTimestamp 未定义,这将使 secondsPassed NaN,这将破坏 rectX 和 rectY。
  • 也从requestAnimationFrame(gameLoop) 调用您的第一个gameLoop,或将timestamp 初始化为document.timeline.currentTime

标签: javascript animation canvas


【解决方案1】:

您的问题是第 3 行中的 let rectX; 创建了一个“未定义”

如果你使用rectX += 1 js 尝试添加 undefined + 1 (自动从 undefined 转换字符串)

sting + int = NaN

let rectX = 0;
let rectY = 0;
let speed = 1;
function update(seconds){
  rectX += (speed * seconds);
  rectY += (speed * seconds);
}

// test:

update(5);
console.log(rectX, rectY); // output is 5 5

【讨论】:

  • 只要修复它仍然是 NaN
  • 这不是一个修复,它是为什么这不起作用的描述。 let rectX = 0; rextX += 1; 这是一个修复提示
  • 并且通常回答状态如何解决它并且解决这个问题仍然会有 NaN
  • string + int = longer string
  • 但如果我给 rectX 或 rectY 一个值,它仍然会给出 NaN。
【解决方案2】:

问题在于,当您最初调用 gameLoop 函数时,您没有将 timeStamp 传递给它。在 gameLoop 内部,timeStamp 未定义,这会破坏其他变量。

您可以在第一次调用时传入当前时间戳。代替 gameLoop()试试

gameLoop(Date.now().getTime())

【讨论】:

  • 他们正在使用 requestAnimationFrame,它传递一个 DOMHighResTimestamp(基本上是自文档存活以来的毫秒数),因此他们将在第二帧中获得的时间戳将在 17 毫秒左右,Date.now().getTime() 将返回自 1970/01/01 以来的毫秒数,因此大约为 1.6 Trillions 毫秒。假设他们希望他们的动画速度在最常见的显示器(60Hz)上大约为每帧 1px,即在第一帧时跳跃 -1e12px。
【解决方案3】:

初始化变量 rectX 和 rectY 可能会有所帮助。

试试这个:

rectX = 0;
rectY = 0;

【讨论】:

  • 但如果我给 rectX 或 rectY 一个值,它仍然会给出 NaN
  • 参见上面@epascarello 的cmets。 (1) 时间戳也未初始化,因此 secondsPassed 也是如此,(2) 记录/或检查表达式的输入,从而给您带来意想不到的结果。
  • 我已经这样做了,尝试记录所有内容,我使用 typeof 查看它是字符串还是数字,但仍然给了我 NaN。太奇怪了,我会尝试再记录一次输入
  • 所有调试信息都应该在问题中,@Tomasnborges
  • 抱歉没有更具体。我将更新我的问题。
猜你喜欢
  • 2022-01-13
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 2021-05-10
  • 2019-12-03
  • 1970-01-01
  • 1970-01-01
  • 2020-08-10
相关资源
最近更新 更多