一尘不染

Javascript:只有在 <script> 结束时才会刷新画布吗?

javascript

我正在使用 Javascript 和画布编写非常基本的代码(刚刚开始学习)。我尝试做一些随机绘图(矩形有 50% 的机会出现在某些位置)。一旦发生这种情况,我希望浏览器等待一秒钟,清除屏幕并立即再次绘制它(视觉上应该立即将一张图替换为另一张图)。

当我这样做时,画布似乎不想更新,它只在主循环结束时更新一次,您可以在下面找到代码:

<script>
  let canvas = document.querySelector("canvas");
  let context = canvas.getContext("2d");

  function wait(ms) {
    var start = new Date().getTime();
    var end = start;
    while (end < start + ms) {
      end = new Date().getTime();
    }
  }

  for (let k = 0; k < 3; k++) {
    context.clearRect(0, 0, canvas.width, canvas.height);
    console.log("First checkpoint");
    for (let i = 0; i < 5; i++) {
      for (j = 0; j < 5; j++) {
        let width_custom = 60;
        let height_custom = 60;
        let gap = 20;
        let x = 100 + (width_custom + gap) * i;
        let y = 100 + (height_custom + gap) * j;

        context.beginPath();
        context.rect(x, y, width_custom, height_custom);
        context.stroke();
        if (Math.random() > 0.5) {
          context.beginPath();
          context.rect(x + 8, y + 8, width_custom - 16, height_custom - 16);
          context.stroke();
        }
      }
    }
    wait(1000); 
    console.log("Second checkpoint");
  }

有没有办法在循环期间强制画布刷新?


阅读 89

收藏
2022-07-26

共1个答案

一尘不染

您的wait函数违背了 javascript 的异步特性。您正在以某种方式阻止程序,因此事情不会被刷新。你应该使用setTimeout这种东西(setInterval甚至更好requestAnimationFrame)。

我准备了如何异步循环和等待的非常令人困惑但有趣的示例。我相信其他人会建议使用Promise。或awaitasync。都很好。

let canvas = document.querySelector("canvas");
let context = canvas.getContext("2d");

my_loop(3)

function my_loop(k) {
  if (k > 0) {
    one_round(1000, function() {
      my_loop(k - 1)
    })
  }
}

function one_round(delay, foo_then) {
  context.clearRect(0, 0, canvas.width, canvas.height);
  for (let i = 0; i < 5; i++) {
    for (j = 0; j < 5; j++) {
      let width_custom = 60;
      let height_custom = 60;
      let gap = 20;
      let x = 100 + (width_custom + gap) * i;
      let y = 100 + (height_custom + gap) * j;
      context.beginPath();
      context.rect(x, y, width_custom, height_custom);
      context.stroke();
      if (Math.random() > 0.5) {
        context.beginPath();
        context.rect(x + 8, y + 8, width_custom - 16, height_custom - 16);
        context.stroke();
      }
    }
  }
  setTimeout(foo_then, delay);
}
<canvas></canvas>
2022-07-26