Skip to content

Instantly share code, notes, and snippets.

@subtleGradient
Created May 3, 2010 21:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save subtleGradient/388624 to your computer and use it in GitHub Desktop.
Save subtleGradient/388624 to your computer and use it in GitHub Desktop.
/*
---
name: fx
description: very basic animation logic.
authors:
- "[Valerio Proietti](http://mad4milk.net)"
- "[Thomas Aylott](http://subtlegradient.com)"
license: "[MIT](http://mootools.net/license.txt)"
provides: fx
...
*/
(function(exports){
var UID = 0, toString = ({}).toString,
instances = {}, timer, fps = 60;
function isArray(object){
return toString.call(object) == '[object Array]';
}
exports.fx = fx;
function fx(options){
if (!this instanceof fx) return new fx(options);
options = options || {};
var self = this,
uid = (UID++).toString(36),
duration = options.duration || 500,
behavior = options.behavior || 'cancel',
render = options.render || function(){},
callBack = options.callBack || function(){},
equation = options.equation || function(p){
return -(Math.cos(Math.PI * p) - 1) / 2;
},
stack = [], from, to, time, timer
;
self.start = function(f, t){
if (timer){
if (behavior == 'cancel') self.stop();
else {
if (behavior == 'stack') stack.push(function(){
self.start(f, t);
});
return self;
}
}
from = !isArray(f) ? [f] : f;
to = !isArray(t) ? [t] : t;
time = +(new Date);
timer = addInstance(uid, self);
return self;
};
self.step = function(){
var now = +(new Date),
factor = (now - time) / duration;
if (factor >= 1) factor = 1;
var computations = [],
delta = equation(factor);
for (var i = 0, l = from.length; i < l; i++)
computations[i] = compute(from[i], to[i], delta);
render.apply(self, computations);
if (factor == 1){
self.stop();
var next = stack.shift();
if (next) next();
callBack();
}
};
self.stop = function(){
timer = removeInstance(uid, self);
return self;
};
};
function compute(from, to, delta){
return (to - from) * delta + from;
};
function loop(){
for (var uid in instances) instances[uid].step();
};
function addInstance(uid, instance){
instances[uid] = instance;
if (!timer) timer = setInterval(loop, Math.round(1000 / fps));
return 1;
};
function removeInstance(uid, instance){
delete instances[uid];
if (timer){
var length = 0;
for (uid in instances) length++;
if (!length) timer = clearInterval(timer);
}
return 0;
};
})(typeof exports != 'undefined' ? exports : this);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment