/*
FxEffectļд˼壬ڲЧĻ
ʵϣFxΪPrototypeЧʱMoo.fxʵ
ʵٵĴ룬õ
*/

var Fx = new Class({


 //ʽִУ¼ͿѡĽӿʵ

 Implements: [Chain, Events, Options],

 

 options: {

  /*

  onStart: $empty, //Чʼʱ¼

  onCancel: $empty, //Чȡʱ¼

  onComplete: $empty, //Чʱ¼

  */  

  fps: 50, //frame per secondÿ֡ڼʱʱ

  unit: false, //λʹ

  duration: 500,
 //ڣЧʱ
  link: 'ignore', //¾ЧתͻʱĴ

  //תʵĿֵı仯ٶȺԸ߿ٶȵı仯
  transition: function(p){

   return -(Math.cos(Math.PI * p) - 1) / 2;

  }

 },


 //캯

 initialize: function(options){

  this.subject = this.subject || this;

  this.setOptions(options);
  //жǷʹ׼ǵڣȡ

  this.options.duration = Fx.Durations[this.options.duration] || this.options.duration.toInt();
  //ͬ¼ݵдɰ汾ʹõwait

  var wait = this.options.wait;
  //ʹþԵڣⲻwaitʱ

  if (wait === false) this.options.link = 'cancel';

 },


 //ÿһִеĲ

 step: function(){
  //ȡǰʱ

  var time = $time();
  //ûʱ

  if (time < this.time + this.options.duration){
   //תЧеıֵ

   var delta = this.options.transition((time - this.time) / this.options.duration);
   //ݱĿֵ

   this.set(this.compute(this.from, this.to, delta));
  //ִн

  } else {
   //ʱֵΪֵ1

   this.set(this.compute(this.from, this.to, 1));

   this.complete();

  }

 },


 //Ŀֵʵ

 set: function(now){

  return now;

 },


  //ݳʼֵֵͱĿֵ
 compute: function(from, to, delta){

  //ʹΪкܶЧʹͬ㷨ʹþ̬

  return Fx.compute(from, to, delta);

 },

 

 //鵱ǰЧ״̬

 check: function(){
  //Чû

  if (!this.timer) return true;

  switch (this.options.link){
   //waitΪfalselinkΪcancelȴеЧֱȡ¿ʼ

   case 'cancel': this.cancel(); return true;
   //linkΪcancelȴǰЧнټЧ

   case 'chain': this.chain(this.start.bind(this, arguments)); return false;
   //ȡֵǵͬignoreֱӺЧɵǰЧ

  }

  return false;

 },


 //Чʼfrom任to

 start: function(from, to){
  //鵱ǰЧ״̬ǷЧ

  if (!this.check(from, to)) return this;

  //ΪطõҪתΪ

  this.from = from;

  this.to = to;

  this.time = 0;
  //ʼʱ

  this.startTimer();
  //onStart¼֪ͨ

  this.onStart();

  return this;

 },


 //Ч

 complete: function(){
  //ֹͣʱonComplete¼

  if (this.stopTimer()) this.onComplete();

  return this;

 },


 //ȡִеЧ
 cancel: function(){

  //ֹͣʱonCancel¼

  if (this.stopTimer()) this.onCancel();

  return this;

 },


 //onStart¼֪ͨ

 onStart: function(){
  //ע⴫¼ĲΪthis.subject

  this.fireEvent('onStart', this.subject);

 },

 

 //onComplete¼֪ͨ

 onComplete: function(){

  //ע⴫¼ĲΪthis.subject

  this.fireEvent('onComplete', this.subject);
  //ʽִ

  if (!this.callChain()) this.fireEvent('onChainComplete', this.subject);

 },

 

 //onCancel¼֪ͨ

 onCancel: function(){

  //onCancel¼ȡʽִУע⴫¼ĲΪthis.subject

  this.fireEvent('onCancel', this.subject).clearChain();

 },


 //ͣЧ

 pause: function(){
  //ֻҪֹͣʱ

  this.stopTimer();

  return this;

 },


 //ЧͣĻָ

 resume: function(){
  //¿ʼʱ䣬Ϊthis.timeѾнȼ¼
Կֱӿʼʱָܻͣǰ״̬
  this.startTimer();

  return this;

 },


 //ֹͣʱ

 stopTimer: function(){
  //ûлֹͣ

  if (!this.timer) return false;
  //this.timeresumeЧָ

  this.time = $time() - this.time;
  //ֹͣʱ

  this.timer = $clear(this.timer);

  return true;

 },


 //ʼʱ

 startTimer: function(){
  //ѿʼʱ

  if (this.timer) return false;
  //ʱ

  this.time = $time() - this.time;
  //ʼʱעҪfps㣬ÿִеʱ

  this.timer = this.step.periodical(Math.round(1000 / this.options.fps), this);

  return true;

 }

 

});


//Ŀֵļ㷨ͬ㷨ʵֲͬתЧ

Fx.compute = function(from, to, delta){

 return (to - from) * delta + from;

};


//ڵļ
Fx.Durations = {'short': 250, 'normal': 500, 'long': 1000};

