Yahoo! UI Library

animation 

Yahoo! UI Library > animation > AnimMgr.js (source view)

/**
 * Handles animation queueing and threading.
 * Used by Anim and subclasses.
 * @class AnimMgr
 * @namespace YAHOO.util
 */
YAHOO.util.AnimMgr = new function() {
   /** 
    * Reference to the animation Interval.
    * @property thread
    * @private
    * @type Int
    */
   var thread = null;
   
   /** 
    * The current queue of registered animation objects.
    * @property queue
    * @private
    * @type Array
    */   
   var queue = [];

   /** 
    * The number of active animations.
    * @property tweenCount
    * @private
    * @type Int
    */      
   var tweenCount = 0;

   /** 
    * Base frame rate (frames per second). 
    * Arbitrarily high for better x-browser calibration (slower browsers drop more frames).
    * @property fps
    * @type Int
    * 
    */
   this.fps = 200;

   /** 
    * Interval delay in milliseconds, defaults to fastest possible.
    * @property delay
    * @type Int
    * 
    */
   this.delay = 1;

   /**
    * Adds an animation instance to the animation queue.
    * All animation instances must be registered in order to animate.
    * @method registerElement
    * @param {object} tween The Anim instance to be be registered
    */
   this.registerElement = function(tween) {
      queue[queue.length] = tween;
      tweenCount += 1;
      tween._onStart.fire();
      this.start();
   };
   
   /**
    * removes an animation instance from the animation queue.
    * All animation instances must be registered in order to animate.
    * @method unRegister
    * @param {object} tween The Anim instance to be be registered
    * @param {Int} index The index of the Anim instance
    * @private
    */
   this.unRegister = function(tween, index) {
      tween._onComplete.fire();
      index = index || getIndex(tween);
      if (index != -1) { queue.splice(index, 1); }
      
      tweenCount -= 1;
      if (tweenCount <= 0) { this.stop(); }
   };
   
   /**
    * Starts the animation thread.
	* Only one thread can run at a time.
    * @method start
    */   
   this.start = function() {
      if (thread === null) { thread = setInterval(this.run, this.delay); }
   };

   /**
    * Stops the animation thread or a specific animation instance.
    * @method stop
    * @param {object} tween A specific Anim instance to stop (optional)
    * If no instance given, Manager stops thread and all animations.
    */   
   this.stop = function(tween) {
      if (!tween) {
         clearInterval(thread);
         for (var i = 0, len = queue.length; i < len; ++i) {
            if (queue[i].isAnimated()) {
               this.unRegister(tween, i);  
            }
         }
         queue = [];
         thread = null;
         tweenCount = 0;
      }
      else {
         this.unRegister(tween);
      }
   };
   
   /**
    * Called per Interval to handle each animation frame.
    * @method run
    */   
   this.run = function() {
      for (var i = 0, len = queue.length; i < len; ++i) {
         var tween = queue[i];
         if ( !tween || !tween.isAnimated() ) { continue; }

         if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
         {
            tween.currentFrame += 1;
            
            if (tween.useSeconds) {
               correctFrame(tween);
            }
            tween._onTween.fire();        
         }
         else { YAHOO.util.AnimMgr.stop(tween, i); }
      }
   };
   
   var getIndex = function(anim) {
      for (var i = 0, len = queue.length; i < len; ++i) {
         if (queue[i] == anim) {
            return i; // note return;
         }
      }
      return -1;
   };
   
   /**
    * On the fly frame correction to keep animation on time.
    * @method correctFrame
    * @private
    * @param {Object} tween The Anim instance being corrected.
    */
   var correctFrame = function(tween) {
      var frames = tween.totalFrames;
      var frame = tween.currentFrame;
      var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
      var elapsed = (new Date() - tween.getStartTime());
      var tweak = 0;
      
      if (elapsed < tween.duration * 1000) { // check if falling behind
         tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
      } else { // went over duration, so jump to end
         tweak = frames - (frame + 1); 
      }
      if (tweak > 0 && isFinite(tweak)) { // adjust if needed
         if (tween.currentFrame + tweak >= frames) {// dont go past last frame
            tweak = frames - (frame + 1);
         }
         
         tween.currentFrame += tweak;     
      }
   };
};

Copyright © 2006 Yahoo! Inc. All rights reserved.