Muhammad Raihan Muhaimin Muhammad Raihan Muhaimin - 5 months ago 12
Javascript Question

Canvas draw image blocked by code below it

Hi I have a following function

render = function ( ctx, img, W, H ) {
ctx.drawImage(img, 0, 0, W, H, 0, 0, W, H);
}


I am calling the function from another function

renderImage(ctx, img, width, height);
for(var i = 0; i < 10000000 ; i++) {
// en expensive for loop
}


The problem I am facing the image doesn't load in the browser until the for loop finishes executing, however it is not clear why the image wait to load until the for loop finishes. Anyone can help? How can I make it load without waiting for the loop to finish executing?

K3N K3N
Answer

JavaScript is single threaded so the browser is prevented from updating the screen while the loop is running.

To solve give the browser a moment to breath using a delay. This will of course make the code run asynchronous so a callback mechanism is possibly required depending on the code's next move.

Example:

renderImage(ctx, img, width, height);

setTimeout(function() {
  for(var i = 0; i < 10000000 ; i++) {
    // en expensive for loop
  }
  // call next step
}, 9);   // delay some arbitrary ms

You can also replace setTimeout() with requestAnimationFrame() which will guarantee time enough to update, but it can also delay the next an entire frame (16.7ms).

renderImage(ctx, img, width, height);

requestAnimationFrame(function() {
  for(var i = 0; i < 10000000 ; i++) {
    // en expensive for loop
  }
  // call next step
});

If the loop is long-running you could consider splitting it up in several segments or use a WebWorker.

See these answers for how to split the loop:

Bonus tip: you don't have to use the clipping parameters to draw a resized image, just provide width and height:

ctx.drawImage(img, 0, 0, W, H);
Comments