Monday, May 9, 2011

Javascript Explorations

Transfering experience from Actionscript to Javascript entails many levels of mind mappings. On the practical level, Actionscript allows the developer a great deal of flexibility and expressibility within a concise object oriented framework.

One of the tomes of power that Actionscript keeps the throne at is animation.
While in the realm of Actionscript we'd be adding event listeners to `ENTER_FRAME`, in Javascript we'd be passing a callback to the `setInterval` function. Enough about Actionscript, let's get down to Javascript.

Any kind of architectural enforcing could work to make things more sane in Javascript land (we don't want to be setting out setInterval sporadocally throughout our code). The downside is that each developer, or each `plug-your-code-to-me` framework may want to do it in a slightly different way, and it's practically impossible to get two frameworks to play nice together if they were all-encompassing in that regard.
This develops a great desire for exploring the method of orchestrating all these animations that jQuery UI Animations take route. Do they have a single `setInterval` that they turn on and off based on what they need? Or do they just spawn out a setInterval for each different thing going on a web page? If it were a single invocation, then is it expected to be exclusive for UI updates, in case we're allowed to hoop up on it in the first place?

Let's hope these questions will lead to some concise and definite answers.

All this talk about animation got my itch going to develop this bit of Javascript test:

var list = [];
var x = document.getElementById('x');

setInterval(function() {
var box = {
d: document.createElement('div'),
t: 0,
x0: Math.random()*400,
y0: Math.random()*400,
};

box.x = box.x0;
box.y = box.y0;

var d = box.d;
d.style.width = '5px';
d.style.height = '5px';
d.style.backgroundColor = "#000";
d.style.position = 'relative';
d.style.left = '100px';
d.style.top = '200px';
x.appendChild(d);

list.push(box);
animateBoxes();
}, 500);

setInterval(animateBoxes, 20);

function animateBoxes(){
for(var i = 0; i < list.length; i++){
var b = list[i];
b.x = b.x0 + b.t*10;
b.y = b.y0 + Math.sin(2*b.t)*30;

b.d.style.left = b.x + "px";
b.d.style.top = b.y + "px";

b.t += 0.02;
}
}


I got it tested here too if you don't really want to create your own files for the testing: http://jsdo.it/arithma/eScx

1 comment:

  1. jquery has one setInterval, that manages all its internal "timers".
    every time you call animate(..) function a new internal "timer" is created and pushed onto a queue of "timers"
    the interval (defined by default to 13ms) runs the timer step function to step a unit until the "end" of a timer is reached, then the timer will be removed from the queue

    when the queue is empty, the interval is cleared.
    when an animation is called and the interval is cleared, a setInterval is called (just once).

    you can also analyze the jquery code:
    http://ajax.googleapis.com/ajax/libs/jquery/1.5/jquery.js

    checking the function [b]animate[/b], you can see it calls the function [b]custom [/b] for every property:
    [code]jQuery.each( prop, function( name, val ) {
    ...
    e.custom( start, end, unit );[/code]
    then custom function:
    [code]custom: function( from, to, unit ) {
    var self = this,
    fx = jQuery.fx;

    this.startTime = jQuery.now();
    this.start = from;
    this.end = to;
    this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
    this.now = this.start;
    this.pos = this.state = 0;

    function t( gotoEnd ) {
    return self.step(gotoEnd);
    }

    t.elem = this.elem;

    if ( t() && jQuery.timers.push(t) && !timerId ) {
    timerId = setInterval(fx.tick, fx.interval);
    }
    }[/code]
    the tick function loops on the timers and calls the timer() (which actually calls the step function as defined above):
    [code]tick: function() {
    var timers = jQuery.timers;

    for ( var i = 0; i < timers.length; i++ ) {
    if ( !timers[i]() ) {
    timers.splice(i--, 1);
    }
    }

    if ( !timers.length ) {
    jQuery.fx.stop();
    }
    }[/code]
    So in summary one interval + animation queue.

    ReplyDelete