Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't we use a for loop to create an animation?

With the help of the jQuery library and the offset() method it seems logical to think that by writing this simple code the element will gradually change position

for (i = 0; i < 900; i = i + .5) { 
    $('#moving-element').offset({ top: i })
}

The browser will stop for a while and will finally move the element to a position 900px apart from the top, no transition can be observed. Out of curiosity i wrote this :

for (i = 0; i < 900; i = i + .5) { 
    $('#moving-element').offset({ top: i }); 
    console.log(i)
}

to see that the console is outputting the succession of numbers fine, but it only offsets the element once the for loop is over.

Why is this not done gradually as the code is being executed?

like image 644
Mg Gm Avatar asked Aug 15 '14 13:08

Mg Gm


2 Answers

Because javascript is a single-threaded event modeled runtime (at least in current incarnations).

This means while you're running your for loop no other tasks can be running. This means accepting user input, updating the screen, etc. So the loop runs entirely through and then displays the final result.

like image 66
tkone Avatar answered Nov 06 '22 10:11

tkone


The problem is that javascript is single-threaded, and it blocks the ui and event queue when processing. You need to use setTimeout or some other asynchronous flow-control mechanism to generate drawing tasks to stick into the event loop so the browser can do other things while doing your animation.

// Our animate function changes the offset, waits a while, then repeats
function animate(n) {
    // Change the offset to the passed in value
    $('#moving-element').offset( {top: n});

    // If the passed in value is equal to 900, stop exection
    if (n === 900)
        return;        

    // Otherwise, set a timer which will trigger our animate function again
    // after 10 milliseconds
    setTimeout(function() {
        // Increment n when passing it into our function
        animate(n++):
    }, 10);
}

// Call the function to begin with
animate(0);

Here is a JSFiddle example which will give you some idea of just how fast for loops are. Upon clicking the button, a for loop will begin execution, and only when it reaches its one millionth iteration will it display an alert on the screen.

like image 34
James Donnelly Avatar answered Nov 06 '22 10:11

James Donnelly