Moving From Flash to Ajax, Javascript Animation Class

After many years of creating Flash-enabled websites (and writing a lot of ActionScript), I decided to explore the use of Ajax. I had grown so accustom to developing websites where page refreshes weren’t required that I rarely created websites using HTML only. From everything that I read prior creating website using Ajax, I thought that it had the promise to replace Flash. My primary reason for exploring the use of Ajax to create websites was because, as I learned more about marketing a website (and how most search engines don’t/can’t index Flash-only sites), I decided that it was better to appear in a search engine’s listing than to have cool navigation (and animation!).

When I first began developing ajax-enabled sites, I did not use an Ajax Framework. I was working on a shopping cart site that was originally created using Flash. I first created a Javascript class to handle the XMLHttpRequest.  This Javascript object was based upon code that I got from a Sitepoint book entitled,  Build Your Own AJAX Web Applications
. I modified it a bit so that it could handle scope issues, but most of the object remained unchanged.

I then created a Javascript animation object that was based upon functions that I found on shiriru.blogspot.com which are based upon equations by Robert Penner. The effects that I am able to create with this class do not compete with the types of effects that I can do using Flash or SwishMax, but it was good enough.

First I instantiate the object:

?View Code JAVASCRIPT
var imAnimate = new imAnimate();

To move an element, I call the following function:

?View Code JAVASCRIPT
imAnimate.animate(element, motion_type, property, easing, end);

Element: The element to be animated.

Motion type: (high, low, slow, fast, fadeIn, fadeout, sizeInc, sizeDec).

Property To Be changed: (width, height, top, left, opacity, font size).

Easing: (easeInBounce, linear, easeInOutBounce, easeOutBounce, easeInOutBack, easeOutBack, easeInBack, easeInOutElastic, easeOutElastic, easeInElastic, easeInOutCirc, easeOutCirc, easeInCirc, easeInOutExpo, easeOutExpo, easeInExpo, easeInOutSine, easeOutSine, easeInSine, easeInOutQuint, easeOutQuint, easeInQuint, easeInOutQuart, easeOutQuart, easeInQuart, easeOutCubic, easeInCubic).

End: The end state of the element. For example if you are changing the “Left” property of the element, this value is the x-coordinate (in pixels) of where you want to the element to stop.

In the shopping cart website, my client wanted the menus to move similar to the menus on Gucci’s site. So I created a menu object (Javascript “class”) and called the following method in order to animate the movement:

?View Code JAVASCRIPT
this.moveMenus = function(dir) {
		var type='high';
		var prop='left';
		var easing='easeOutExpo';
		var end = (dir == 'next') ? '-235' : '235';
		thisMenu.imAnimate.animate(thisMenu.menuParent, type, prop, easing, end);
};

While I suppose that creating animation with Javascript Frameworks like JQuery or Dojo Toolkit may be more sophisticated, but I would not be surprised if Robert Penner’s equations form the basis of their animation.

Here’s the Code:

?Download imAnimate.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
//http://shiriru.blogspot.com/2007/10/javascript-animation-make-things-move.html
//based on equations by Robert Penner http://robertpenner.com/
 
function imAnimate() {
	this.begin = null;
	this.end = null;
	this.startX = null;
	this.startY = null;
	this.startW = null;
	this.startH = null;
	this.startF = null;
	this.duration = 1000;
	this.fps = 35;
	this.obj = null;
	this.prop = null;
	this.easing = null;
 
	this.init = function(elm) {
		this.startX = elm.style.left;
		this.startY = elm.style.top;
		this.startW = elm.style.width;
		this.startH = elm.style.height;
		this.startF = elm.style.fontSize;
	};
 
	this.resetObj = function () {
		this.obj.style.left=this.startX;
		this.obj.style.top=this.startX;
		this.obj.style.width=this.startW;
		this.obj.style.height=this.startH;
		this.obj.style.fontSize=this.startF;
		if(!window.attachEvent) this.obj.style.opacity=1;
		else  this.obj.style.filter = "alpha(opacity=100)";
	}
 
	this.animate = function (elm, type, prop, easing, end) {
		this.obj = elm;
		this.init(elm);
		this.prop=prop;
		if (type=='high') this.fps=35;
		if (type=='med') this.fps=21;
		if (type=='low')  this.fps=6;
		if (type=='slow') this.duration=6000;
		if (type=='fast')  this.duration=600;
		if (type=='fadeIn')  {this.begin=0; this.end=1; }
		if (type=='fadeOut')  {this.begin=1; this.end=0;}
		if (type=='sizeInc')  {this.begin=0; this.end=end; }
		if (type=='sizeDec')  {
			if (prop=="width") {
				this.begin=elm.style.width; 
			} else if (prop=="height") {
				this.begin=elm.style.height; 
			}
			this.end=0;
		}
		if (prop=="left") {
			if ((BrowserDetect.browser == "Explorer") && (parseInt(BrowserDetect.version) >= 6) && (BrowserDetect.OS == "Windows")) {
				this.begin=elm.style.pixelLeft;	
			} else {
				this.begin=elm.offsetLeft;	
			}
			this.end=end;
		}
		if (prop=="top") {
			if ((BrowserDetect.browser == "Explorer") && (parseInt(BrowserDetect.version) >= 6) && (BrowserDetect.OS == "Windows")) {
				this.begin=elm.style.top;
			} else {
				this.begin=elm.offsetTop;
			}
			this.end=end;
		}
		if (prop=='fontSize')  {this.begin=15; this.end=30;}
		this.easing=easing;
		this.doAnimation();
	};
 
	this.doAnimation = function () {
		var begin 		= parseInt(this.begin);
		var end 		= parseInt(this.end);
		var change = (begin>=0) ? end-begin : end;
		var interval    = Math.ceil(1000/this.fps);
    	var totalframes = Math.ceil(this.duration/interval);
    	var step        = change/totalframes;
		var self = this;
		for(i=1;i <= totalframes;i++) {
     		(function() {
         		var frame=i;
         		function innerChangeWidth() {
             		var functionName=eval("self."+self.easing);
             		var increase=functionName(frame,begin,change,totalframes);
             		var slope=increase-begin;
 
             		unit=(self.prop=='opacity') ? '' : 'px';
             		if(window.attachEvent && !unit) { 
                  		increase*=100; 
                  		self.obj.style.zoom = 1;
                  		self.obj.style.filter = "alpha(opacity=" + increase + ")";
              		} else {
                     	self.obj.style[self.prop] = increase+unit; 
              		}
    			}
    			timer = setTimeout(innerChangeWidth,interval*frame);
              })();
 		}
	};
 
	this.linear = function (t, b, c, d) {
 		var m=c/d;
 		var a =t/d;
 		return m*t + b;
	};
 
	this.easeInQuad = function (t, b, c, d) {
 		return c*(t/=d)*t + b;
	};
 
	this.easeOutQuad = function (t, b, c, d) {
 		return -c *(t/=d)*(t-2) + b;
	};
 
	this.easeInOutQuad = function (t, b, c, d) {
 		if ((t/=d/2) < 1) return c/2*t*t + b;
 		return -c/2 * ((--t)*(t-2) - 1) + b;
	};
 
	this.easeInCubic = function (t, b, c, d) {
 		return c*(t/=d)*t*t + b;
	};
 
	this.easeOutCubic = function (t, b, c, d) {
 		return c*((t=t/d-1)*t*t + 1) + b;
	};
 
	this.easeInOutCubic = function (t, b, c, d) {
 		if ((t/=d/2) < 1) return c/2*t*t*t + b;
 		return c/2*((t-=2)*t*t + 2) + b;
	};
 
	this.easeInQuart = function (t, b, c, d) {
 		return c*(t/=d)*t*t*t + b;
	};
 
	this.easeOutQuart = function (t, b, c, d) {
 
 		return -c * ((t=t/d-1)*t*t*t - 1) + b;
	};
 
	this.easeInOutQuart = function (t, b, c, d) {
 		if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
 		return -c/2 * ((t-=2)*t*t*t - 2) + b;
	};
 
	this.easeInQuint = function (t, b, c, d) {
 		return c*(t/=d)*t*t*t*t + b;
	};
 
	this.easeOutQuint = function (t, b, c, d) {
 		return c*((t=t/d-1)*t*t*t*t + 1) + b;
	};
 
	this.easeInOutQuint = function (t, b, c, d) {
 		if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
 		return c/2*((t-=2)*t*t*t*t + 2) + b;
	};
 
	this.easeInSine = function (t, b, c, d) {
		return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
	};
 
	this.easeOutSine = function (t, b, c, d) {
 		return c * Math.sin(t/d * (Math.PI/2)) + b;
	};
 
	this.easeInOutSine = function (t, b, c, d) {
 		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	};
 
	this.easeInExpo = function (t, b, c, d) {
 		return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
	};
 
	this.easeOutExpo = function (t, b, c, d) {
 		return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
	};
 
	this.easeInOutExpo = function (t, b, c, d) {
 		if (t==0) return b;
 		if (t==d) return b+c;
 		if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
 		return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
	};
 
	this.easeInCirc = function (t, b, c, d) {
 		return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
	};
 
	this.easeOutCirc = function (t, b, c, d) {
		return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
	};
 
	this.easeInOutCirc = function (t, b, c, d) {
 		if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
 		return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
	};
 
	//a: amplitude (optional), p: period (optional)
	this.easeInElastic = function (t, b, c, d, a, p) {
 		if (t==0) {
  			return b; 
 		} 
 		if ((t/=d)==1) {
  			return b+c;  
 		}
 		if (!p) {
  			p=d*.3;
 		}
 		if (a < Math.abs(c)) {
   			a=c; 
   			s=p/4; 
 		} else {
  			a=Math.abs(c);
  			s = p/(2*Math.PI) * Math.asin(c/a);
 		}
 
 		return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
	};
 
	this.easeOutElastic = function (t, b, c, d, a, p) {
 		if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
 		if (a < Math.abs(c)) { a=c; var s=p/4; }
 		else {   a=Math.abs(c); var s = p/(2*Math.PI) * Math.asin (c/a);}
 		return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
 
	};
 
	this.easeInOutElastic = function (t, b, c, d, a, p) {
 		if (t==0) return b;  
 		if ((t/=d/2)==2) return b+c;  
 		if (!p) p=d*(.3*1.5);
 		if (a < Math.abs(c)) { 
  			a=c; var s=p/4; 
 		} else {
  			a=Math.abs(c);
  			var s = p/(2*Math.PI) * Math.asin (c/a);
 		}
 		if (t < 1) {
  			return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
 		}
 		return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
	};
 
	this.easeInBack = function (t, b, c, d, s) {
 		if (s == undefined) s = 1.70158;
 		return c*(t/=d)*t*((s+1)*t - s) + b;
	};
 
	this.easeOutBack = function (t, b, c, d, s) {
 		if (s == undefined) s = 1.70158;
 		return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
	};
 
	this.easeInOutBack = function (t, b, c, d, s) {
 		if (s == undefined) s = 1.70158; 
 		if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
 		return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
	};
 
	this.easeInBounce = function (t, b, c, d) {
 		return c - easeOutBounce (d-t, 0, c, d) + b;
	};
 
	this.easeOutBounce = function (t, b, c, d) {
 		if ((t/=d) < (1/2.75)) {
  			return c*(7.5625*t*t) + b;
 		} else if (t < (2/2.75)) {
  			return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
 		} else if (t < (2.5/2.75)) {
  			return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
 		} else {
  			return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
 		}
	};
 
	this.easeInOutBounce = function (t, b, c, d) {
 		if (t < d/2) return easeInBounce (t*2, 0, c, d) * .5 + b;
 		return easeOutBounce (t*2-d, 0, c, d) * .5 + c*.5 + b;
	};
}
 
//===========================
//Motion Types
//() - no value
//high
//low
//slow
//fast
//fadeIn
//fadeOut
//sizeInc
//sizeDec
 
//============================
// Ease Types
//easeInBounce
//linear
//easeInOutBounce
//easeOutBounce
//easeInOutBack
//easeOutBack
//easeInBack
//easeInOutElastic
//easeOutElastic
//easeInElastic
//easeInOutCirc
//easeOutCirc
//easeInCirc
//easeInOutExpo
//easeOutExpo
//easeInExpo
//easeInOutSine
//easeOutSine
//easeInSine
//easeInOutQuint
//easeOutQuint
//easeInQuint
//easeInOutQuart
//easeOutQuart
//easeInQuart
//easeOutCubic
//easeInCubic
 
//============================
//Prop Types
 
//width
//height
//left
//top
//opacity
//fontSize
Thisis a test
Be Sociable, Share!
Javascript does not have classes, but it does have constructors which do what classes do

Checkout My New Site - T-shirts For Geeks