Question

I have already tried my luck and searched a lot but could not find a solution to my issue. The function in question is supposed to draw a set of lines using jcanvas and pause the drawing according to prerecorded times. Instead it just draws the entire lines at once. Here is the jQuery code in question:

$("#start").click(function(){
        $("canvas").css("display","block"); 
        var obj = {  strokeStyle: "#000",  strokeWidth: 6,  rounded: true};
        for (i=0;i<counter;i++)
        {
            obj['x'+(i+1)] = arrX[i]; 
            obj['y'+(i+1)] = arrY[i] - 12; 
            setTimeout(function() {
                var interval = setInterval(function() {
                    $("canvas").drawLine(obj);
                }, 0);

            }, timeDiffs[i]);                               
        }
});
Was it helpful?

Solution

Because the loop finishes before your setTimeout() callback is run, your callback will always reference the final state of the object (that is, its state after the entire loop has run).

To fix this, you can wrap your setTimeout() callback in a closure. By wrapping the callback in a closure function, I am capturing the state of the obj variable. However, in this case, because objects are passes by reference in JavaScript, I have cloned the object (using $.extend) to ensure that its current state (properties and all) is preserved.

setTimeout((function(obj) {
    return function() {
        var interval = setInterval(function() {
            $("canvas").drawLine(obj);
        }, 0);
    };
}($.extend({}, obj))), timeDiffs[i]);

FWIW, there is an extensive examination of this issue on StackOverflow.

OTHER TIPS

just a simplification of Caleb531's point

$("#start").click(function(){

    $("canvas").css("display","block"); 
    var obj = {  strokeStyle: "#000",  strokeWidth: 6,  rounded: true};
    for (i=0;i<counter;i++)
    {
      (function(){
        obj['x'+(i+1)] = arrX[i]; 
        obj['y'+(i+1)] = arrY[i] - 12; 

        var incremental = $.extend({}, obj);

        setTimeout(function() {
            var interval = setInterval(function() {
                $("canvas").drawLine(incremental);
            }, 0);

        }, timeDiffs[i]);      
      })();                         
    }
});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top