I am writing very basic code hear (just started learning) using Javascript & canvas. I try to do some random drawing (rectangles have 50% chance to appear on certain spots). Once this happens I want browser to wait one second, clear the screen and instantly draw it again (visually one drawing should be instantly replaced by another).
When I do so, it seems like canvas does not want to update, it only updates once when main loop ends, you can find code below:
<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");
}
Is there any way to force canvas to refresh during the loop?
Best, Mat
Your wait
function goes against the asynchronous nature of javascript. You are blocking the program in a way so things don't get refreshed. You should be using setTimeout
for this kind of things (or setInterval
or even better requestAnimationFrame
).
I have prepared quite confusing but fun example how to loop asynchronously and wait. I'm sure other people will suggest to use Promise
instead. Or await
and async
. It's all good.
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>