Introduction
This article will look at a very simple animation framework I've developed in JavaScript.
Background
Sometimes it's the little things that make the difference in a website. How content fades in and out or how a place holder resizes.
I've been putting the little touches into one of my web pages, and found it can be tedious and slow to render if not done correctly. The key is not to let each animation handle its own rendering.
If you start 3 animations where each animation updates its own control, if the update interval for the animations is 24 frames per second, the browser could end up having to redraw 72 times a second.
The key is to control the redraws centrally, so even with 100 animations in action, there would only be 24 redraws per second.
Prerequisites
The animation framework builds on top of other frameworks I have developed. Before implementing the animation framework, you must implement the following frameworks:
The Code
The following is the animation framework. An implementation example will follow:
var uiAnimation = function(target, propertyName, from, to, valueSuffix, duration) {
this.Target = typeof target == 'object' ? target : document.getElementById('target').style;
this.PropertyName = propertyName;
this.From = parseInt(from, 10);
this.To = parseInt(to, 10);
this.ValueSuffix = valueSuffix;
this.Duration = parseInt(duration, 10);
this.FrameValues = new Array();
this.CurrentFrame = 0;
this.LastFrame = 0;
this.Complete = new uiEvent();
var step = (to - from) / duration;
var cur = from + step;
var cFrame = 0;
var dir = to < from ? 'down' : 'up';
while ((dir == 'down' && cur > to) || (dir == 'up' && cur < to)) {
this.FrameValues[this.FrameValues.length] = this.ValueSuffix.replace('@@', cur);
this.LastFrame = cFrame;
cFrame++;
cur += step;
}
this.FrameValues[this.FrameValues.length - 1] = this.ValueSuffix.replace('@@', this.To);
}
var uiAnimationHandler = function() {
this.Timer = new uiTimer(1000 / 24);
this.Animations = new Array();
this.Frame = 0;
this.NextFrame = function() {
for (var x = 0; x < this.Animations.length; x++) {
var a = this.Animations[x];
if (a != null) {
if (a.CurrentFrame <= a.LastFrame) {
if (a.FrameValues[a.CurrentFrame] != null) {
a.Target[a.PropertyName] = a.FrameValues[a.CurrentFrame];
a.CurrentFrame++;
if (a.CurrentFrame > a.LastFrame) {
this.Animations[x].Complete.Fire();
this.Animations[x] = null;
}
}
}
}
}
};
this.Timer.OnTick.Register(this.NextFrame, this);
this.Register = function(ani) { this.Animations[this.Animations.length] = ani; };
}
var AnimationManager = new uiAnimationHandler();
The central animation handler is of type uiAnimationHandler
. An instance is declared as AnimationManager
.
The individual animations are of type uiAnimation
, which has the following constructor:
uiAnimation(targetObject, 'property', from, to, 'valueString', frameCount)
targetObject
: This is the object which contains the property to be animated. In most instances this will be the style object of an element.property
: This is the property on the target object which is to be animated.from
: The start value for the animation.to
: The end value for the animation.valueString
: CSS values aren't just numbers. The value string needs to contain '@@'. This is replaced by the value when animating.frameCount
: The animation framework runs at 24 frames per second. This is the number of frames you want the animation to run for.
The following is the constructor to move a div
's left position from 100 to 500 across 48 frames (2 seconds):
var ani = new uiAnimation(div.style, 'left', 100, 500, '@@px', 48);
This then needs to be registered with the animation manager.
AnimationManager.Register(ani);
The following example, when run, will add 300, 50px by 50px div
s to the body
and then animate each one on a random point to point animation within an 800px by 800px region.
for (var x = 0; x < 300; x++) {
var div = document.createElement('div');
var left = Math.random() * 800;
var top = Math.random() * 800;
div.style.position = 'absolute';
div.style.top = top + 'px';
div.style.left = left + 'px';
div.style.width = '50px';
div.style.width = '50px';
div.style.backgroundColor = '#a2bd30';
div.innerHTML = ' '
document.getElementsByTagName('body')[0].appendChild(div);
var mat = new uiAnimation(div.style, 'left', Math.random() * 800,
Math.random() * 800, '@@px', 40);
AnimationManager.Register(mat);
mat = new uiAnimation(div.style, 'top', Math.random() * 800,
Math.random() * 800, '@@px', 40);
AnimationManager.Register(mat);
}
Points of Interest
I was amazed at how well this worked. Both IE 8 and Chrome could easily render the 300 squares and the animation without flickering.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.