Config
Table of Contents

Class

O.Animation

At its core, O.Animation just repeatedly calls a method, O.Animation#drawFrame, over a given time period, supplying it with a number between 0 and 1 to tell it how far through the animation it currently is. This number is modified according to the easing function specified.

The default implementation will set a numeric property on an object, interpolating between the initial value of the property and the value it's asked to transition to. If this is what you want to do, simply initialise your O.Animation instance with an "object" and a "property" value.

For animating something other than a numeric property, override O.Animation#prepare and O.Animation#drawFrame methods.

"use strict";

( function ( NS ) {

// List of currently active animations
var animations = [];

// Draw the next frame in all currently active animations.
var nextFrame = function () {
 // Cache to local variable for speed
 var anims = animations,
   l = anims.length,
   time = NS.RunLoop.frameStartTime,
   objAnimations, i,
   hasMultiple, animation, object, animTime, duration;

 if ( l ) {
   // Request first to get in shortest time.
   NS.RunLoop.invokeInNextFrame( nextFrame );

   while ( l-- ) {
     objAnimations = anims[l];
     i = objAnimations.length;
     hasMultiple = i > 1;
     if ( hasMultiple ) {
       object = objAnimations[0].object;
       object.beginPropertyChanges();
     }
     while ( i-- ) {
       animation = objAnimations[i];
       animTime = time - animation.startTime;
       // For Safari 7, sigh.
       if ( animTime === time ) {
         animation.startTime = time;
         animTime = 0;
       }
       duration = animation.duration;
       if ( animTime < duration ) {
         animation.drawFrame(
           // Normalised position along timeline [0..1].
           animation.ease( animTime / duration ),
           // Normalised time animation has been running.
           animTime
         );
       } else {
         animation.drawFrame( 1, duration );
         animation.stop();
       }
     }
     if ( hasMultiple ) {
       object.endPropertyChanges();
     }
   }
 }
};

var meta = NS.meta;

NS.Animation = NS.Class({

 init: function ( mixin ) {
   this.duration = this.duration;
   this.ease = this.ease;
   this.isRunning = false;
   this.startTime = 0;

   this.startValue = null;
   this.endValue = null;
   this.deltaValue = null;

   NS.extend( this, mixin );
 },

Property

O.Animation#duration

  • Number

The length, in milliseconds, that the animation should last.

duration: 300,

Property

O.Animation#ease

  • Function

The easing function to use for the animation.

ease: NS.Easing.ease,

Property

O.Animation#isRunning

  • Boolean

Is the animation currently in progress?

Private Property

O.Animation#startTime

  • Number
  • private

A timestamp for when the animation began. Do not alter manually.

Property

O.Animation#object

  • Object

The object on which to set the property during animation.

Property

O.Animation#property

  • String

The name of the property to set on the object being animated.

Method

O.Animation#animate( value, duration, ease )

Transition to a new (given) value. If it is currently in the middle of an animation, that will be stopped and the new animation will transition from whatever the current value is to the new value.

Parameters

value* The new value to animate to.
durationNumber Optional The length of the animation (in ms).
easeFunction Optional The easing function to use.

Returns

O.Animation Returns self.

animate: function ( value, duration, ease ) {
   if ( this.isRunning ) {
     this.stop();
   }
   if ( duration != null ) {
     this.duration = duration;
   }
   if ( ease != null ) {
     this.ease = ease;
   }

   // Prepare any values. Check we've actually got something to animate.
   if ( !this.prepare( value ) ) {
     return this;
   }

   var object = this.object,
     metadata = meta( object ),
     objAnimations = metadata.animations || ( metadata.animations = [] );

   this.startTime = 0;

   // Start loop if no current animations
   if ( !animations.length ) {
     NS.RunLoop.invokeInNextFrame( nextFrame );
   }

   // And add objectAnimations to animation queue
   if ( !objAnimations.length ) {
     animations.push( objAnimations );
   }
   objAnimations.push( this );

   // Now running
   this.isRunning = true;
   // Let object know animation has begun.
   if ( object.willAnimate ) {
     object.willAnimate( this );
   }
   return this;
 },

Protected Method

O.Animation#prepare( value )

Called at the beginning of a new animation to perform any calculations that are constant in every frame, or otherwise initialise the animation.

Parameters

value* The new value to be transitioned to.

Returns

Boolean Is there anything to actually animate. Returns false if the value is already at the desired end point.

prepare: function ( value ) {
   if ( typeof value === 'object' ) {
     this.startValue = value.startValue;
     this.endValue = value.endValue;
   } else {
     this.startValue = this.object.get( this.property );
     this.endValue = value;
   }
   this.deltaValue = this.endValue - this.startValue;

   return !!this.deltaValue;
 },

Protected Method

O.Animation#drawFrame( position )

Called 60 times a second (or as frequently as the browser can manage) whilst the animation is in progress to draw each frame in the animation. The default implementation just interpolates from the start (numeric) value to the end (numeric)value and sets the <#property> on the <#object> with the new value. Override this method to do something different when drawing a frame.

Parameters

positionNumber A number, normally between 0 and 1, giving the position in the animation, modified by the easing function (the easing function may cause the number to go beyond 0 and 1).
drawFrame: function ( position/*, time*/ ) {
   // And interpolate to find new value.
   var value = position < 1 ?
     this.startValue + ( position * this.deltaValue ) :
     this.endValue;

   this.object.set( this.property, value );
 },

Method

O.Animation#stop()

Stop the animation (at the current position), if it is in progress.

Returns

O.Animation Returns self.

stop: function () {
   if ( this.isRunning ) {
     // Remove from animation lists.
     var object = this.object,
       objAnimations = meta( object ).animations;
     objAnimations.erase( this );

     if ( !objAnimations.length ) {
       animations.erase( objAnimations );
     }
     // Not running any more
     this.isRunning = false;
     // Let object know animation has finished.
     if ( object.didAnimate ) {
       object.didAnimate( this );
     }
   }

   return this;
 }
});

}( O ) );
Animation
Application
Core
DataStore
DOM
DragDrop
Foundation
IO
Localisation
Selection
Parser
TimeZones
Storage
Touch
CollectionViews
UA
ContainerViews
ControlViews
PanelViews
View