6 description: Contains the basic animation logic to be extended by all other Fx Classes.
8 license: MIT-style license.
10 requires: [Chain, Events, Options]
19 var Fx = this.Fx = new Class({
21 Implements: [Chain, Events, Options],
37 initialize: function(options){
38 this.subject = this.subject || this;
39 this.setOptions(options);
42 getTransition: function(){
44 return -(Math.cos(Math.PI * p) - 1) / 2;
49 if (this.options.frameSkip){
50 var diff = (this.time != null) ? (now - this.time) : 0, frames = diff / this.frameInterval;
57 if (this.frame < this.frames){
58 var delta = this.transition(this.frame / this.frames);
59 this.set(this.compute(this.from, this.to, delta));
61 this.frame = this.frames;
62 this.set(this.compute(this.from, this.to, 1));
71 compute: function(from, to, delta){
72 return Fx.compute(from, to, delta);
76 if (!this.isRunning()) return true;
77 switch (this.options.link){
78 case 'cancel': this.cancel(); return true;
79 case 'chain': this.chain(this.caller.pass(arguments, this)); return false;
84 start: function(from, to){
85 if (!this.check(from, to)) return this;
88 this.frame = (this.options.frameSkip) ? 0 : -1;
90 this.transition = this.getTransition();
91 var frames = this.options.frames, fps = this.options.fps, duration = this.options.duration;
92 this.duration = Fx.Durations[duration] || duration.toInt();
93 this.frameInterval = 1000 / fps;
94 this.frames = frames || Math.round(this.duration / this.frameInterval);
95 this.fireEvent('start', this.subject);
96 pushInstance.call(this, fps);
101 if (this.isRunning()){
103 pullInstance.call(this, this.options.fps);
104 if (this.frames == this.frame){
105 this.fireEvent('complete', this.subject);
106 if (!this.callChain()) this.fireEvent('chainComplete', this.subject);
108 this.fireEvent('stop', this.subject);
115 if (this.isRunning()){
117 pullInstance.call(this, this.options.fps);
118 this.frame = this.frames;
119 this.fireEvent('cancel', this.subject).clearChain();
125 if (this.isRunning()){
127 pullInstance.call(this, this.options.fps);
133 if (this.isPaused()) pushInstance.call(this, this.options.fps);
137 isRunning: function(){
138 var list = instances[this.options.fps];
139 return list && list.contains(this);
142 isPaused: function(){
143 return (this.frame < this.frames) && !this.isRunning();
148 Fx.compute = function(from, to, delta){
149 return (to - from) * delta + from;
152 Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};
156 var instances = {}, timers = {};
158 var loop = function(){
159 var now = Date.now();
160 for (var i = this.length; i--;){
161 var instance = this[i];
162 if (instance) instance.step(now);
166 var pushInstance = function(fps){
167 var list = instances[fps] || (instances[fps] = []);
169 if (!timers[fps]) timers[fps] = loop.periodical(Math.round(1000 / fps), list);
172 var pullInstance = function(fps){
173 var list = instances[fps];
176 if (!list.length && timers[fps]){
177 delete instances[fps];
178 timers[fps] = clearInterval(timers[fps]);