It's late and the part of my brain where Douglas Crockford lives is closed. Ive tried a few things but nothing's doing as expected.
I've got a canvas where I draw a 2 lines, then fade them out on a timer but only the last line in the loop is being faded out. Here's my fiddle, look down to line 50ish in the JS, to see it in action drag your mouse around in the bottom right pane:
this is the function, basically the timeout only gets the last value in the loop, I've seen this before and I'm sure if I wasn't so delirious it might be simpler. Here's the function in particular:
function update()
{
var i;
this.context.lineWidth = BRUSH_SIZE;
this.context.strokeStyle = "rgba(" + COLOR[0] + ", " + COLOR[1] + ", " + COLOR[2] + ", " + BRUSH_PRESSURE + ")";
for (i = 0; i < scope.painters.length; i++)
{
scope.context.beginPath();
var dx = scope.painters[i].dx;
var dy = scope.painters[i].dy;
scope.context.moveTo(dx, dy);
var dx1 = scope.painters[i].ax = (scope.painters[i].ax + (scope.painters[i].dx - scope.mouseX) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dx -= dx1;
var dx2 = scope.painters[i].dx;
var dy1 = scope.painters[i].ay = (scope.painters[i].ay + (scope.painters[i].dy - scope.mouseY) * scope.painters[i].div) * scope.painters[i].ease;
scope.painters[i].dy -= dy1;
var dy2 = scope.painters[i].dy;
scope.context.lineTo(dx2, dy2);
scope.context.stroke();
for(j=FADESTEPS;j>0;j--)
{
setTimeout(function()
{
var x=dx,y=dy,x2=dx2,y2=dy2;
scope.context.beginPath();
scope.context.lineWidth=BRUSH_SIZE+1;
scope.context.moveTo(x, y);
scope.context.strokeStyle = "rgba(" + 255 + ", " + 255 + ", " + 255 + ", " + .3 + ")";
scope.context.lineTo(x2, y2);
scope.context.stroke();
scope.context.lineWidth=BRUSH_SIZE;
},
DURATION/j);
}
}
}
j
is a global.closePath()
whenever you're done with the paths you start withbeginPath()
Explanation
The other answers about
dx
anddy
being passed from the higher scope are the right answers though. Async functions defined in synchronous for loops will take the last version of the state.The problem is that the variables
dx
,dy
, etc that you refer to in the function you pass tosetTimeout()
are defined in the surrounding scope and by the time any of the timeouts actually runs these variables all hold the values from the last iteration of the loop(s).You need to create an extra containing function to close over the values from each iteration. Try something like the following:
This creates a new anonymous function for each iteration of the
j=FADESTEPS
loop, executing it immediately and passing thedx
, etc. values as they were at the time each iteration of the loop ran, and moving thex
,y
, etc. variables out of your existing function and making them parameters of the new one so then by the time the timeout runs it will use the correct values.I would suggest you to use an array and store the points avoiding
setTimeOut
call in a loop. Somewhat like this.I know this is not exactly what you need, but I think this can be modified to get it.
You can try something like this:
Or another way (as soon as you do not use IE, but let it learn canvas at first :))
ps: there is no need in set of extra functions (the reasons are clear)