Reputation: 258
I have built an image up on a canvas with drawImage using several pieces.
I now want to try either load them in 1 by 1, or, attempt animate them or modify the size of the pieces used to make up the full image after they have initially loaded.
I am having trouble getting them to work with a setTimeout
function, is this even a suitable method? or is there a better way?
Here is my original working canvas built with several image pieces: https://codepen.io/anon/pen/MyaMOK
Here is my attempt loading them in 1 by 1 and the setTimeout
:
setTimeout(function(){
ctx.drawImage(img, piece.sx, piece.sy, piece.sWidth, piece.sHeight, piece.x, piece.y, piece.w, piece.h);
},100*tileCount);
https://codepen.io/anon/pen/RaWzgJ
It seems to just load 1 "piece" in the bottom right corner, and none of the others, though this method seems to work fine outside the setTimeout
.
Can anyone suggest a workable solution?
Upvotes: 0
Views: 900
Reputation: 2666
I took your code and modified it by adding console.log
before the setTimeout
function and within the callback
of the setTimeout
function.
The result was that the loops were working as expected. The piece
object was getting updated for every iteration.
However, the setTimeout
functions were called only after the entire loop was exhausted, and to my surprise, taken the same values for piece
object.
The reason why it behaved like this, according to me, is thus:
setTimeout
function only registers the callback
function (to be executed later) but does not block the loop (it is asynchronous).
Therefore, the loop continues without executing any of the callbacks within setTimeout
and piece
gets updated through out.
When the loop is exhausted, the callback
functions start executing. However, all the callbacks are referring to the same piece
object (due to hoisting
and because javascipt is not block-scoped), hence they all get the same value.
Conclusion: all the image pieces get correctly outputted, but they get outputted at the same place, one on-top of another.
Why putting setTimeout
in another function works:
Putting setTimeout
in another function works because calling the new function creates a new scope with its own piece
object, i.e., it is no longer sharing from the same global piece
object.
Upvotes: 0
Reputation: 258
Figured it out.
making function within a function = bad. moved the setTimeout
function outside of the for loop and passed the variables to it from within, updated working codepen is here:
https://codepen.io/anon/pen/RaWzgJ
Upvotes: 2