无法在 javascript 中强制刷新画布

Posted

技术标签:

【中文标题】无法在 javascript 中强制刷新画布【英文标题】:Cannot force a canvas refresh in javascript 【发布时间】:2021-12-16 11:35:01 【问题描述】:

我试图让游戏定期刷新画布,主循环包括一个重播屏幕的函数和一个让计算机计算移动的函数(如果轮到它的话)。玩家可以选择 1-9 步,然后,如果计算机在玩家最后一次移动后还没有离开,它将使用一个非常深的树来计算它的移动。计算机移动需要几秒钟才能移动。尽管在计算机移动之前已经更新了画布,但直到计算机离开后它才会刷新,这意味着玩家和计算机移动是同时显示的,而不是顺序显示的。我可以做些什么来确保画布每 100 毫秒更新一次,而不是在计算机计算出它的移动之后才更新?

function playGame() 
    function doKeyDown(evt) 
        console.log(evt.keyCode)
        if (evt.keyCode > 48 && evt.keyCode < 58)  
            game.makeMove(evt.keyCode-48); // 1-9 are user actions
        
    

    function mainLoop(ctx, game, board) 
        board.showBoard(ctx); // display board
        game.makeMove(0); // zero is computer move
    

    Canvas.canvas = document.getElementById("myCanvas");
    let game = new Game();
    let board = new Board(game);
    window.addEventListener( "keydown", doKeyDown, true);
    Canvas.ctx = Canvas.canvas.getContext('2d');
    setInterval(() => mainLoop(Canvas.ctx, game, board), 100);
;  

document.addEventListener('DOMContentLoaded', playGame);

【问题讨论】:

欢迎来到 javascript 的单线程特性。当 JS 主动运行时,浏览器不能做任何事情,包括渲染屏幕。 如果可能的话,考虑使用 Web Workers 并行计算一些东西。 【参考方案1】:

有几件事绝对可以帮助您确保画布按预期刷新。

    将计算密集型任务转移到 Web Worker。

    使用window.requestAnimationFrame() 而不是setInterval() 进行渲染。

网络工作者

Web Workers 非常适合将计算密集型任务转移到; Web Workers 的 MDN 文档指出,“工作线程可以在不干扰用户界面的情况下执行任务。”这将允许在不阻塞渲染线程的情况下计算计算机的移动。

有关 Web Workers 的更多信息,请参阅:Web Workers (MDN Web Docs)

window.requestAnimationFrame()

window.requestAnimationFrame() 方法是当前实现动画的最佳方法。本质上,它会导致浏览器在下一次重绘之前执行提供的回调。这是对之前的setTimeout()setInterval() 方法的改进,因为它只在浏览器重绘之前调用回调,换句话说,它减少了使用setTimeout()setInterval() 可能导致的不必要的计算。

有关window.requestAnimationFrame() 的更多信息,请参阅:window.requestAnimationFrame() (MDN Web Docs)

有关为什么选择 window.requestAnimationFrame() 而不是 setTimeout()setInterval() 的精彩短文,请参阅 Matt West 的这篇文章:Efficient Animations with requestAnimationFrame

工作示例:

我已经使用codesandbox.io 编写了一个小的工作示例;正如我所描述的,它使用 Web Workers 和 requestAnimationFrame()。请注意,它使用计时器代替计算密集型任务,它使用 5 秒计时器来模拟计算机移动,并使用 1 秒计时器来模拟玩家移动。

代码沙盒:Web Worker & requestAnimationFrame() Example

【讨论】:

以上是关于无法在 javascript 中强制刷新画布的主要内容,如果未能解决你的问题,请参考以下文章

如何强制刷新javascript [重复]

F5刷新与Ctrl+F5强制刷新的区别

Android怎么强制刷新View

如何强制客户端刷新 JavaScript 文件?

我可以使用 JavaScript 在 iframe 上强制刷新吗?

乐视电视强制刷机方法