Simple Object-Oriented Fade Animation
Normally, I'd just use MooTools for fade animations, but a long-time client wanted a simple, one-time popup that notified her patients that her doctor's office had moved—a temporary courtesy to be removed in a few months.To make the custom popup just a little nicer, I wanted a simple fade effect without the extra framework code. Of course, I could have just copied and pasted the methods in MooTools, but I was feeling creative and shopped around to see if any native JS solutions existed.
I found a solution I liked, though it lacks the greater flexibility of a more object-oriented approach. It also sets foreign attributes, FadeState and FadeTimeLeft, directly on the element
<div id="fadeEl" FadeState="-2" FadeTimeLeft="33"> I am the fade element. </div>and passes a spliced-together variable that looks up the same element over and over again: document.getElementById(eid),
setTimeout("animateFade(" + new Date().getTime() + ",'" + eid + "')", 33);neither of which are optimal.
The logic was there, however, and it wasn't hard to convert into an object. The nice thing about objects is that an object is just that: A flexible model of something that once modeled can be easily reused. So, I revamped the function provided there to make it less intrusive and more modular.
I'd originally posted the following re-working in the comments on that site, but this is a slightly more polished example.
Basic Object
The AnimateFade Class
// declare class so we can use the "new" keyword to create unique instances var AnimateFade = function(elmOrElmId, duration, state) { this.setOptions(elmOrElmId, duration, state); this.animate(); }; // prototype its methods AnimateFade.prototype = { setOptions: function(elmOrElmId, duration, state) { this.fadeDuration = duration; this.element = (typeof elmOrElmId == 'string') ? document.getElementById(elmOrElmId) : elmOrElmId; this.fadeState = (state && state == 1) ? 1 : 0; this.fadeTimeLeft = duration; this.lastTick = this.newTick(); }, newTick: function() { return (new Date).getTime(); }, getElapsedTicks: function() { return this.currentTick - this.lastTick; }, animate: function() { this.currentTick = this.newTick(); var self = this; var elapsedTicks = this.getElapsedTicks(); // helper function, called in the timeout below, // recurses with correct reference to "this" var helper = function() { self.animate(); }; if (this.fadeTimeLeft <= elapsedTicks) { this.element.style.opacity = this.fadeState; this.element.style.filter = 'alpha(opacity = ' + (this.fadeState * 100) + ')'; return; } this.fadeTimeLeft -= elapsedTicks; var newOptVal = this.fadeTimeLeft / this.fadeDuration; newOptVal = (this.fadeState == 1) ? (1 - newOptVal) : newOptVal; this.element.style.opacity = newOptVal; this.element.style.filter = 'alpha(opacity = ' + (newOptVal * 100) + ')'; this.lastTick = this.currentTick; this.currentTick = this.newTick(); setTimeout(helper, 24); } }; // initializer function var init = function(elmsOrElmIdArr, duration, state) { for (var i = 0, l = elmsOrElmIdArr.length; i < l; i++) { // "new" keyword creates unique instance new AnimateFade(elmsOrElmIdArr[i], duration, state); } };
Instantiations
Single/Multiple Elements, Single Duration and Fade State
To instantiate with one or more elements that will all fade in or out for the same duration:// pass in either string id or element reference // Example A: fade just one element var myOnlyElement = ['myUniqueId']; // Example B: fade multiple elements var myMultElms = ['myId', document.getElementsByTagName('div')[7], 'anotherId']; // how long fade should last var myDuration = 1000;//1,000 milliseconds, or 1 second // start fading out init(myMultElms, myDuration); // or fading in init(myMultElms, myDuration, 1);
Multiple Elements, Durations, and Fade States
Or retool the initializer function...// initializer function capitalizing on parallel arrays var init = function(elmsOrElmIdArr, duration, state) { for (var i = 0, l = elmsOrElmIdArr.length; i < l; i++) { // "new" keyword creates unique instance new AnimateFade(elmsOrElmIdArr[i], duration[i], state[i]); } };...to take full advantage of arrays, simultaneously fading multiple elements in and out for different lengths of time:
// set parallel arrays var myElms = [elm1, elm2, elm3]; var myDurations = [1000, 2500, 300]; var myStates = [0, 1, 0]; // start effects init(myElms, myDurations, myStates); // elm1 fades out in 1 second // elm2 fades in in 2-and-a-half seconds // elm3 fades out in 3/10ths of a secondThis could be useful if you wanted to fade in one set of elements while simultaneously fading out another set, perhaps a confirmation dialog and its acknowledge that the user's choice has either been implemented or canceled. Or whatever.