cdf
Version:
A library for creating oldschool demo-like animations with JavaScript
141 lines (117 loc) • 3.69 kB
JavaScript
(function(global,cdf_varname){var lib = global[cdf_varname] || {};
var rfm = lib.requestAnimFrame || requestAnimationFrame.bind(window);
var State = lib.State = function () {
if(this instanceof State) {
this.callbacks = {init: null, animate: null, end: null, finish: null};
this.arguments = [];
} else {
return new State()
.init(arguments[0])
.animate(arguments[1])
.finish(arguments[2]);
}
};
var triggerStart = function(instance, args){
instance.arguments = args;
if(instance.callbacks.animate){
var isAnimating = true;
var repeats = instance.repeats;
var startTime = new Date();
var frameNum = 0;
var nextFrame = function () {
for(var i=0;i<repeats;i++) {
if (isAnimating) {
var thisArg = {
state: instance,
realFrame: frameNum,
time: new Date() - startTime,
frame:frameNum*repeats+i,
finish: function () {
isAnimating = false;
triggerFinish(instance, arguments);
}
};
instance.callbacks.animate.apply(thisArg, args);
}
}
frameNum++;
if(isAnimating)rfm(nextFrame);
};
nextFrame();
}
else triggerFinish(instance, args);
};
var triggerFinish = function(instance, args){
if(instance.callbacks.finish){
instance.callbacks.finish.apply({state:instance}, instance.arguments);
}
if(instance.callbacks.end)instance.callbacks.end.apply({state:instance}, args);
};
var triggerInit = function(instance){
if(instance.callbacks.init) {
var thisArg = {
state: instance,
start: function () {
triggerStart(instance, arguments);
}
};
instance.callbacks.init.call(thisArg, lib);
} else triggerStart(instance,[]);
};
State.prototype = {
init: function (callback) {
this.callbacks.init = callback;
return this;
},
animate: function (callback, repeats) {
this.repeats = Math.ceil(repeats || 1);
this.callbacks.animate = callback;
return this;
},
finish: function (callback) {
this.callbacks.finish = callback;
return this;
},
start: function(callback, rightNow){
if(callback)this.callbacks.end = callback;
var instance = this;
if(rightNow) triggerInit(instance);
else document.addEventListener('DOMContentLoaded', function(){ triggerInit(instance)});
return this;
}
};
var StateMachine = lib.StateMachine = function(){
this.states = [];
};
var triggerTimelineStart = function (instance, callback) {
var states = instance.states;
var runState = function(stateNum){
var state = states[stateNum].state;
if(state) {
instance.currentState = state;
state.start(function () {
runState(stateNum+1);
}, true);
} else {
if(callback && callback.call) callback.call(instance);
}
};
runState(0);
};
StateMachine.prototype = {
state: function(name, state){
if(!(state instanceof State)){
state = State.apply(null, [].slice.call(arguments,1) );
}
this.states.push({name:name,state:state});
return this;
},
start:function(callback, rightNow){
var instance = this;
if(rightNow) triggerTimelineStart(this, callback);
else lib.init(function(){
triggerTimelineStart(instance, callback);
});
}
};
if(cdf_varname) global[cdf_varname]=lib;})(window, (typeof module!=='undefined'&& module.exports)?false:'cdf');