Wednesday, 3 March 2010

jQuery Animation

I'm an absolute fan of jQuery. I have to admit that first time I checked it it didn't appeal to me that much. I was missing the Prototype.js "OOP on asteroids" features that turn JavaScript into an even more powerful beast. That's not what jQuery is for, jQuery is mainly thought for the User Interface (events, styling, animation...), AJAX and some utility functions. That's fine, cause if you need extra functionality in your Web Browser tier (some business logic, validators...) for which you would prefer a more "class based programming" approach, you still can add prototype.js to the mix (I haven't tried it, but in principle both libraries can play well together).

I already knew that the animation features in jQuery are a real joy to use, but the animation chaining is specially superb. This sample is, simply said, beautiful.
I guess (understanding jQuery source code is not an easy task, so I'm just doing guess work) that the jQuery object has some kind of animation queue, and each call to .animate() queues an animation there.

The problem is that I needed something the other way around. Instead of chaining different animations over a same object, I wanted to chain the same animation on different objects (and with a small delay between each animation to make the effect more noticeable).

So I've created an animator object that makes use of the jQuery animation features. It would be simple to generalize it to accept different animation functions, delays... It's rather simple code, but it involves closures, callbacks, and for some reason I feel like it could be useful to someone.

Here goes the main code:



var animator = function(items, delay)
{
this.animItems = items;
this.animatingIndex = 0;
this.delay = delay;
};

animator.prototype.animate = function()
{
this.animatingIndex = 0;
this.animateNext();
};

animator.prototype.animateNext = function()
{
//the old closure trick
var self = this;
//if this is the last one, do not invoke a new animateNext
if (this.animatingIndex == this.animItems.length -1)
{
$(this.animItems[this.animatingIndex]).toggle(this.delay);
}
else
{
//added the timeout thing to add a pause effect after each item is displayed
$(this.animItems[this.animatingIndex]).toggle(this.delay, function()
{
setTimeout(function(){self.animateNext();}, 300);
});
}
this.animatingIndex++;
}


and here goes what it does:






item1

item2

item3


you can get the full code here

2 comments:

  1. Interesante tu código.
    Respecto a lo que dices de combinar jQuery y prototype sí que se puede. Pero para que no haya conflicto lo que hago es lo siguiente:

    var $j = jQuery.noConflict();

    Y a partir de este momento uso "$j" en vez de "$" para referirme a jQuery

    ReplyDelete
  2. Gracies pol comment xefe.
    Sí, lo que dices ye xusto lo que lleí dalguna vegada na páxina de jQuery.

    ReplyDelete