An Introduction to Javascript Animation

Animating elements with Javascript using DOM compliant, non-invasive code

Color fading and resizing to notify user for dynamic changes

created on 29.08.2005

Introduction

Javascript animations are seen more and more in our daily web routines. Most can be annoying too, if they simply serve the purpose to lamely look cool, while they may actually only distract the user.

However, when used properly, they can really add to the user experience, and increase the useability of your site. Also, with the advent of the DOM, the more widespread usage of new generation browsers, and the adoption of xmlHttpRequest and other technologies which all together are called AJAX, the need for notifying user with what is going on with simple animations can become a necessity, such as using fading colors and resizing elements. Actually, I am putting such an animation to good use on this very page, while step-by-step explaining the main animation function for resizing. The principles are all the same, but the color fading was inspired by the Yellow Fade Technique For Dummies, this one is a versatile function that you can fade any color to any color. It is also a very light-weight script that you can modify to use for any type of animation, as you see on this page. If you have specific questions for implementing the scripts in your own sites, feel free to drop me a mail using the contact page oh hesido.com.

Samples

Fade, single direction, no memory

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Fade, both directions, w / memory

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Resize, both directions, w / memory

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Hover over me!

Move objects, w / memory
Click Me!

Some details of this technique

The animation code, explained

Doing the resize animation (Main function)

Javascript
function doWidthChangeMem(elem,startWidth,endWidth,steps,intervals,powr) { 
//Width changer with Memory by www.hesido.com
    if (elem.widthChangeMemInt)
	window.clearInterval(elem.widthChangeMemInt);
    var actStep = 0;
    elem.widthChangeMemInt = window.setInterval(
	function() { 
	  elem.currentWidth = easeInOut(startWidth,endWidth,steps,actStep,powr);
	  elem.style.width = elem.currentWidth + "px"; 
	  actStep++;
	  if (actStep > steps) window.clearInterval(elem.widthChangeMemInt);
	} 
	,intervals)
}

Here is a step by step explanation of the function, please hover for highlighting the step:

  1. Terminate, if there is any, ongoing animation
  2. Reset animation step to 0
  3. Assign interval function with interval id passed to element
  4. Anonymous function declared within our function, so we can safely use variables from our parent function, even though it is an interval function that runs in the window scope.
  5. Get a value using easeInOut, embedding onto the element.
  6. Use that value to set the object's width
  7. Increase step number
  8. If step number is bigger, self-terminate.

Here's a brief explanation of variables used:

elem: element that we're going to animate
startWidth: starting width of animation
endWidth: target width of animation
steps: total steps of animation
intervals: intervals the animation will be done in miliseconds
powr: value used for determining ease-in and out.
----
elem.widthChangeMemInt: The interval animation value for self inhibition.
elem.currenWidth: The objects 'memory' of its last set width.
actstep: actual step of the animation, increased 1 per every execution.

Initiating animation (with memory)

Memory here refers to the fact that the animation will be able to handle from a previously terminated or finished animation, and that for each step, Memory will be embedded to the object. Same type of animations in your project should sport same type of Memory variables, so animation can be picked up from where it was left, and different type of animations with different Memory variables should not interfere with eachother.

There can be many events that may fire up the animation, here I use mouseover and mouseout events, and we'll be seeing the width sizer animation function. I must stress, for the simplicity, I used the .onevent type event attaching, which is the old and destructive method. To be able to attach multiple function to a particular type of event, you must use addEventListener and attachEvent. attachEvent does not return element that we are attached the event to 'this', but it always returns the'window' element with 'this'. There are ways to get around this but it is not the main issue of this article. (if you are programming a User Javascript, you should always use non destructive methods, addEventListener should suffice.)

Javascript
myElement.onmouseover = widthChange; 
myElement.onmouseout = widthRestore; 

function widthChange() { 
    if (!this.currentWidth) this.currentWidth = 150; 
	//if no memory is set, set it first; 
    doWidthChangeMem(this,this.currentWidth,170,10,10,0.5); 
    } 
function widthRestore() { 
    if (!this.currentWidth) return; 
    doWidthChangeMem(this,this.currentWidth,150,10,10,0.5); 
    }

Here, I need an animation that will be reversible, as I want my object to return to its initial values after mouseout. The animation should be able to terminate early, and that's why I need an animation memory for the object. The reason I set the initial value right in javascript, instead of reading it from the style of the object is because there is currently big discrepancies between how browsers read active styles, it is much cleaner to set the initial value right in javascript. There are quite a number of ways you can read styles from objects if you really want it, so you can have it your way. Those numbers will make sense when you see the doWidthChangeMem function.

Producing an animation step value at a given step

Javascript
function easeInOut(minValue,maxValue,totalSteps,actualStep,powr) { 
//Generic Animation Step Value Generator By www.hesido.com 
    var delta = maxValue - minValue; 
    var stepp = minValue+(Math.pow(((1 / totalSteps) * actualStep), powr) * delta); 
    return Math.ceil(stepp) 
    } 

This generic animation step value churner is my best friend. We can simply give minValue / maxValue, the totalSteps of the animation, and the actual step we request the value of, with a power (powr) so we can decide for ease-in and ease-out type values: powr > 1 produces ease-in, < 1 produces ease-out, = 1 produces linear animations. By increasing the actualStep in every animation step, we simply have each animation value on request. Choosing between ease-in and ease-out is enough for me, but you can prepare a function that will return an ease-in + ease-out values, or you can break the animation into two parts and use this cute(!) little function.

Final Words

I hope you like this piece of code. Solutions in the script required serious thinking!