Creating a JQuery plugin to create smooth animations

Posted on September 13, 2009. Filed under: Web Development | Tags: , , , |

A few days ago came in my head a question, can we simulate the smooth animations that we can easily make in Silverlight/WPF using JavaScript and html? Of course not all of them, WPF has storyboards that are a very powerful way to create animations. But some simple animations are very easy to create using JQuery.

Without searching much if there’s a solution for this, I decided to create a JQuery plugin where you can configure an animation using CSS classes. Another option to create rich animations is use the animate method of JQuery or the JQuery UI effects.

A very cool example to do is create an animated button using several background images and sliding doors CSS technique. Instead of having one image for idle, one for hover and one for active, we can have n images for each state.

Button background

To create my hover animation I made 5 variations of the blue glow.

Download the source code in this link to see the code running (4 samples and the sliding doors button).

Lets go to the code

First we create our JQuery plugin and define a few global variables:

jQuery.fn.extend({
 cssAnimator: function(animTime, configKey, target) {

 var $sender = $(this);
 var $target = target ? target : $(this);

 var animationStack = new Array();
 var timeout = null;
 var lastClass = "";
});

In the constructor of the plugin there’s 3 parameters:

animTime: interval time to change between css classes in milliseconds.
configKey: name of the animation that was defined in the json configuration variable (we will see that later).
target: optional, in case we want to execute the animation on a different target, I mean, another element that is not the element that triggered the animation.

Now we create an object using JSON syntase where we will define our animation so it will be easily reused later.


var configArray =
 {
 "link":
 { "hover":
 ["hover1", "hover2", "hover3", "hover4", "hover5", "hover"],
 "leave":
 ["hover5", "hover4", "hover3", "hover2", "hover1", "normal"],
 "mousedown":
 ["active1", "active2", "active"],
 "mouseup":
 ["active2", "active1", "hover"]
 },
"AnimationKey":
 { "hover":
 ["..."],
 "leave":
 ["..."],
 "mousedown":
 ["..."],
 "mouseup":
 ["..."]
 }

};

Note that “hover”, “leave”, “mousedown” e “mouseup” is where the sequence of css classes that the object will use is stored, creating the animation in this order. I possible to leave “mousedown” e “mouseup” (or the others) without any style, just create an empty array in JSON “[]”. Where we have “link” and “AnimationKey” is where is defined the name of the animation that is used as a parameter in the plugin constructor.

The following code create the event handlers for mouseover and mouseout events for the element $(this), creator of the animation. Basically, it reads the configuration variable and call the updateAnimation method. The animation that came from the config variable is stored in an array, where each item of the array is a step of the animation.


$sender.hover(function() {
 if(configArray[configKey]["hover"].length > 0){
 animationStack = new Array();
 for (var i = 0; i < configArray&#91;configKey&#93;&#91;"hover"&#93;.length; i++) {
 animationStack.push(configArray&#91;configKey&#93;&#91;"hover"&#93;&#91;i&#93;);
 }
 if (timeout == null)
 timeout = setTimeout(updateAnimation, animTime);
 }
 },
 function() {
 if(configArray&#91;configKey&#93;&#91;"leave"&#93;.length > 0){
 animationStack = new Array();
 for (var i = 0; i < configArray&#91;configKey&#93;&#91;"leave"&#93;.length; i++) {
 animationStack.push(configArray&#91;configKey&#93;&#91;"leave"&#93;&#91;i&#93;);
 }
 if (timeout == null)
 timeout = setTimeout(updateAnimation, animTime);
 }
 });
&#91;/sourcecode&#93;

The method that change the css classes in the target and continue the animation is defined below:

&#91;sourcecode language='jscript'&#93;
function updateAnimation() {
 if (animationStack.length > 0) {

 if (animationStack[0] != lastClass) {
 $target.addClass(animationStack[0]);
 $target.removeClass(lastClass);
 lastClass = animationStack[0];
 }
 animationStack.splice(0, 1);

 if (animationStack.length > 0) {
 timeout = setTimeout(updateAnimation, animTime);
 }
 else {
 timeout = null;
 }
 }
 }

Here, basically, what is done is remove the old style, add the next one of the animation and call himself in a setTimeout.

Below follow an example of how you could define the CSS:

a.button {
 background-color: transparent;
 background-image: url(img/button_bg_right.png);
 background-repeat: no-repeat;
 background-position: right -78px;    
 display: block;
 float: left;
 font-size: 86%;
 font-weight: bold;
 height: 26px;
 overflow: hidden;
 padding-right: 20px;
 margin-right:10px;
 text-decoration: none;
 color: #ffffff !important;
}

a.button span {
 background-color: transparent;
 background-image: url(img/button_bg_left.png);    
 background-repeat: no-repeat;
 background-position: left -78px;
 display: block;
 line-height: 15px;
 padding: 5px 0px 6px 20px;
}
/* button states */
a.button.normal {
 background-position: right -78px;    
}
a.button.normal span {
 background-position: left -78px;
} 

a.button.hover {
 background-position: right -104px;
}
a.button.hover span {
 background-position: left -104px;
}
a.button.hover1 {
 background-position: right -52px;
}
a.button.hover1 span {
 background-position: left -52px;
}
a.button.hover2 {
 background-position: right -26px;
}
a.button.hover2 span {
 background-position: left -26px;
}
a.button.hover3 {
 background-position: right top;
}
a.button.hover3 span {
 background-position: left top;
}
a.button.active {
 background-position: right -130px;    
}
a.button.active span {
 background-position: left -130px;
}

How to use the plugin in you code:


$(document).ready(
 function() {

 $("#link1").cssAnimator(90, "button");

 $(".link").each(function() {
 $(this).cssAnimator(140, "link");
 });
 $("#nameTextbox").cssAnimator(100, "tooltip", $("#tooltip_content"));

Download the source code in this link
to see the code running (4 samples and the sliding doors button).

Don’t forget to comment about what you thought of the post, also suggestions, question, bugs and critics =)

 

Read Full Post | Make a Comment ( None so far )

Liked it here?
Why not try sites on the blogroll...