首页 > 解决方案 > 在 HTML 画布上闪烁图像

问题描述

我正在制作一个利用 HTML 画布并在其上绘制图像的游戏。每秒 60 次,它清除屏幕并重绘所有元素以创建动画。但是,当我使用图像而不仅仅是形状时,图像会在那里,但会闪入和闪出并且不会一直可见。我以前做过这样的游戏(https://graphics-game.napoleon1027.repl.co/),它完全由正方形和圆形组成,从来没有问题。然后,当我添加图像时,它开始闪烁。

<!DOCTYPE html>
<html>

<body>

    <canvas id="canvas" width="900" height="600" style="border:1px solid #d3d3d3;">
    </canvas>

    <script>
        var xcoord = 50
        var ycoord = 50
        function drawscreen() {
            var ctx = document.getElementById('canvas').getContext('2d');
            void ctx.clearRect(0, 0, 900, 600);
            image = new Image()
            image.src = "https://upload.wikimedia.org/wikipedia/en/c/c8/Very_Black_screen.jpg"
            void ctx.drawImage(image, 0, 0, 200, 200, xcoord, ycoord, 50, 50);
            ycoord++
            xcoord++

        }

        setInterval(drawscreen, 16);
    </script>

</body>

</html>

标签: htmlimageanimationcanvas

解决方案


我没有用您提供的几行代码重现您的闪烁行为。但是,您可以做一些事情来优化您的代码,从这里可以看到:

  • 在绘制框架时执行尽可能少的操作:
    • 只获取一次画布绘图上下文
    • 仅加载一次图像
  • 用于window.requestAnimationFrame在客户端准备绘制新帧时运行您的绘图功能(目标为 60fps)

window.addEventListener('DOMContentLoaded', _e => {

  const c = document.querySelector('#game-screen');
  if (!c || !c.getContext)
    return;
  
  runGame();

  function runGame() {
    //Resources
    const ctx = c.getContext('2d');
    const image = new Image();
    image.src = "https://picsum.photos/200";
    //Game state
    let xcoord = 50;
    let ycoord = 50;
    //Last rendered frame timestamp
    let lastTs;

    //Launch animation
    window.requestAnimationFrame(drawFrame);

    function drawFrame(timestamp) {
      //Draw frame
      ctx.clearRect(0, 0, 900, 600);
      ctx.drawImage(image, 0, 0, 200, 200, xcoord, ycoord, 50, 50);
      //Don't count on actual frame rate to compute moves
      //ycoord++; xcoord++; //Will appear slower if frameRate on client < 60fps
      updatePos(timestamp, lastTs);
      lastTs = timestamp;
      
      //Carry on animation
      window.requestAnimationFrame(drawFrame);
    }
    
    function updatePos(timestamp, lastTs) {
      //Move picture diagonaly at 60px/s
      if (lastTs) {
        const delta = timestamp - lastTs;
        const deltaXY = Math.floor(delta * 60 / 1000); //60px per second
        ycoord += deltaXY;
        xcoord += deltaXY;
      }
    }
  }
  
});
canvas {
  border: 1px solid black;
}
<canvas id="game-screen" width="900" height="600">
Canvas not supported
</canvas>


推荐阅读