topical media & game development
lib-flex-animation-code-10-gs-TweenLite.ax
lib-flex-animation-code-10-gs-TweenLite.ax
(swf
)
[ flash
]
flex
/*
VERSION: 9.22
DATE: 10/16/2008
ACTIONSCRIPT VERSION: 3.0 (AS2 version is also available)
UPDATES & MORE DETAILED DOCUMENTATION AT: http://www.@file.com
DESCRIPTION:
Tweening. We all do it. Most of us have learned to avoid Adobe's Tween class in favor of a more powerful engine
that requires less code (e.g. Tweener). Each has its own strengths & weaknesses. A few years back,
I created @ax-lib-flex-animation-code-10-gs-TweenLite because I needed a very compact tweening engine that was fast and efficient (I couldn't
afford the file size bloat that came with the other tweening engines). It quickly became integral to my work
flow. I figured others might be able to benefit from it, so I released it publicly. Over the past few years,
@ax-lib-flex-animation-code-10-gs-TweenLite has grown more popular than I could have imagined.
Since then, I've added new capabilities while trying to keep file size way down (3K). TweenFilterLite extends
@ax-lib-flex-animation-code-10-gs-TweenLite and adds the ability to tween filters including ColorMatrixFilter effects like saturation, contrast,
brightness, hue, and even colorization but it only adds about 3k to the file size. Same syntax as @ax-lib-flex-animation-code-10-gs-TweenLite.
There are AS2 and AS3 versions of both of the classes ready for download. TweenMax adds even more features to
TweenFilterLite including bezier tweening, pause/resume, sequencing, and much more. (see www.TweenMax.com)
I know what you're thinking - "if it's so 'lightweight', it's probably missing a lot of features which makes
me nervous about using it as my main tweening engine." It is true that it doesn't have the same feature set
as some other tweening engines, but I can honestly say that after using it on almost every project I've worked
on over the last few years (many award-winning flash apps for fortune-500 companies), it has never let me down.
I never found myself needing some other functionality. You can tween any property (including a DisplayObject's
volume and color), use any easing function, build in delays, callback functions, pass arguments to that
callback function, and even tween arrays all with one line of code. If you need more features, you can always
step up to TweenFilterLite or TweenMax.
I haven't been able to find a faster tween engine either. See an interactive speed comparison
of various tweening engines at http://blog.greensock.com/tweeing-speed-test/.
ARGUMENTS:
1) duration : Number - Duration (in seconds) of the effect
3)
package gs {
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.TimerEvent;
import flash.geom.ColorTransform;
import flash.utils.*;
public class @ax-lib-flex-animation-code-10-gs-TweenLite {
public static var version:Number = 9.22;
public static var killDelayedCallsTo:Function = @ax-lib-flex-animation-code-10-gs-TweenLite.killTweensOf;
public static var defaultEase:Function = @ax-lib-flex-animation-code-10-gs-TweenLite.easeOut;
public static var overwriteManager:Object; //makes it possible to integrate the gs.utils.tween.OverwriteManager for adding autoOverwrite capabilities
public static var currentTime:uint;
public static var masterList:Dictionary = new Dictionary(false); //Holds references to all our instances.
private static var _classInitted:Boolean;
private static var _sprite:Sprite = new Sprite(); //A reference to the sprite that we use to drive all our ENTER_FRAME events.
private static var _timer:Timer = new Timer(2000);
public var duration:Number; //Duration (in seconds)
public var vars:Object; //Variables (holds things like alpha or y or whatever we're tweening)
public var delay:Number; //Delay (in seconds)
public var startTime:Number; //Start time
public var initTime:Number; //Time of initialization. Remember, we can build in delays so this property tells us when the frame action was born, not when it actually started doing anything.
public var tweens:Array; //Contains parsed data for each property that's being tweened (target, property, start, change, and name).
public var target:Object; //Target object
public var forceActive:Boolean;
public var ease:Function;
public var initted:Boolean;
public var combinedTimeScale:Number; //even though @ax-lib-flex-animation-code-10-gs-TweenLite doesn't use this variable, TweenFilterLite and TweenMax do and it optimized things to store it here, particularly for TweenGroup
public var gc:Boolean; //flagged for garbage collection
public var started:Boolean;
protected var _subTweens:Array; //Only used for associated sub-tweens like tint and volume
protected var _hst:Boolean; //Has sub-tweens. Tracking this as a Boolean value is faster than checking _subTweens.length
protected var _hasUpdate:Boolean; //has onUpdate. Tracking this as a Boolean value is faster than checking this.vars.onUpdate == null.
protected var _isDisplayObject:Boolean; //We need to know if the target is a DisplayObject so that we can apply visibility changes, do tint and Sound tweens, etc
protected var _specialVars:Object; //Helps when using @fileVars, TweenFilterLiteVars, or TweenMaxVars as the this.vars object because certain properties are only exposed via vars.exposedProps (for example, the "visible" property is Boolean, so we cannot normally check to see if it's undefined)
public function @ax-lib-flex-animation-code-10-gs-TweenLite(target:Object, vars:Object) {
if (vars;
this.duration = vars.delay || 0;
this.combinedTimeScale = duration == 0 && this.delay == 0);
this.target = target is DisplayObject);
if (!(this.vars.ease is Function)) {
this.vars.ease = defaultEase;
}
if (this.vars.easeParams != null) {
this.vars.proxiedEase = this.vars.ease;
this.vars.ease = easeProxy;
}
this.ease = this.vars.ease;
if (!isNaN(Number(this.vars.autoAlpha))) {
this.vars.alpha = Number(this.vars.autoAlpha);
this.vars.visible = (this.vars.alpha > 0);
}
_specialVars = (this.vars.isTV == true) ? this.vars.exposedProps : this.vars; //for @fileVars, TweenFilterLiteVars, and TweenMaxVars
this.tweens = [];
_subTweens = [];
_hst = this.initted = false;
this.initTime = currentTime;
this.startTime = this.initTime + (this.delay * 1000);
var mode:int = (vars.overwrite > 1)) ? overwriteManager.mode : int(target] == undefined || (target] = [];
}
masterList[hrp:Boolean = false, hrp && overwriteManager.enabled) {
overwriteManager.manageOverwrites(this, masterList[this.target]);
}
if (this.target is Array) {
var endArray:Array = this.vars.endArray || [];
for (i = 0; i < endArray.length; i++) {
if (this.target[i] != endArray[i] && this.target[i] != undefined) {
this.tweens[this.tweens.length] = [this.target, i.toString(), this.target[i], endArray[i] - this.target[i], i.toString()]; //[object, property, start, change, name]
}
}
} else {
if ((typeof(_specialVars.tint) != "undefined" || this.vars.removeTint == true) && _isDisplayObject) { //If we're trying to change the color of a DisplayObject, then set up a quasai proxy using an instance of a @ax-lib-flex-animation-code-10-gs-TweenLite to control the color.
var clr:ColorTransform = this.target.transform.colorTransform;
var endClr:ColorTransform = new ColorTransform();
if (_specialVars.alpha != undefined) {
endClr.alphaMultiplier = _specialVars.alpha;
delete _specialVars.alpha;
} else {
endClr.alphaMultiplier = this.target.alpha;
}
if (this.vars.removeTint != true && ((_specialVars.tint != null && _specialVars.tint != "") || _specialVars.tint == 0)) { //In case they're actually trying to remove the colorization, they should pass in null or "" for the tint
endClr.color = _specialVars.tint;
}
addSubTween("tint", tintProxy, {progress:0}, {progress:1}, {target:this.target, color:clr, endColor:endClr});
}
if (_specialVars.frame != null && _isDisplayObject) {
addSubTween("frame", frameProxy, {frame:this.target.currentFrame}, {frame:_specialVars.frame}, {target:this.target});
}
if (!isNaN(this.vars.volume) && this.target.hasOwnProperty("soundTransform")) { //If we're trying to change the volume of an object with a soundTransform property, then set up a quasai proxy using an instance of a @ax-lib-flex-animation-code-10-gs-TweenLite to control the volume.
addSubTween("volume", volumeProxy, this.target.soundTransform, {volume:this.vars.volume}, {target:this.target});
}
for (p in _specialVars) {
if (p == "ease" || p == "delay" || p == "overwrite" || p == "onComplete" || p == "onCompleteParams" || p == "runBackwards" || p == "visible" || p == "autoOverwrite" || p == "persist" || p == "onUpdate" || p == "onUpdateParams" || p == "autoAlpha" || (p == "timeScale" && !(this.target is @ax-lib-flex-animation-code-10-gs-TweenLite)) || p == "onStart" || p == "onStartParams" ||p == "renderOnStart" || p == "proxiedEase" || p == "easeParams" || (reservedProps.indexOf(" " + p + " ") != -1)) {
} else if (!(_isDisplayObject && (p == "tint" || p == "removeTint" || p == "frame")) && !(p == "volume" && this.target.hasOwnProperty("soundTransform"))) {
//if (this.target.hasOwnProperty(p)) { //REMOVED because there's a bug in Flash Player 10 (Beta) that incorrectly reports that DisplayObjects don't have a "z" property. This check wasn't entirely necessary anyway - it just prevented runtime errors if/when developers tried tweening properties that didn't exist.
if (typeof(_specialVars[p]) == "number") {
this.tweens[this.tweens.length] = [this.target, p, this.target[p], _specialVars[p] - this.target[p], p]; //[object, property, start, change, name]
} else {
this.tweens[this.tweens.length] = [this.target, p, this.target[p], Number(_specialVars[p]), p]; //[object, property, start, change, name]
}
//}
}
}
}
if (this.vars.runBackwards == true) {
var tp:Object;
for (i = this.tweens.length - 1; i > -1; i--) {
tp = this.tweens[i];
tp[2] += tp[3];
tp[3] *= -1;
}
}
if (_specialVars.visible == true && _isDisplayObject) {
this.target.visible = true;
}
if (this.vars.onUpdate != null) {
_hasUpdate = true;
}
this.initted = true;
}
protected function addSubTween(proxy:Function, props:Object, name, proxy:target, info:props) {
if (typeof(target, p, props[p] - name]; //[object, property, start, change, name]
} else {
this.tweens[this.tweens.length] = [target[p], Number(name]; //[object, property, start, change, name]
}
}
_hst = true; //has sub tweens. We track this with a boolean value as opposed to checking _subTweens.length for speed purposes
}
public static function to(duration:Number, target, vars);
}
public static function from(duration:Number, vars.runBackwards = true;
return new @ax-lib-flex-animation-code-10-gs-TweenLite(duration, delay:Number, onCompleteParams:Array = null):@ax-lib-flex-animation-code-10-gs-TweenLite {
return new @ax-lib-flex-animation-code-10-gs-TweenLite(delay, onComplete:onCompleteParams, overwrite:0});
}
public function render(t - this.startTime) / 1000, factor:Number, tp:Object, i:int;
if (time >= this.duration) {
time = this.duration;
factor = (this.ease == this.vars.ease || this.duration == 0.001) ? 1 : 0; //to accommodate @fileGroup.reverse(). Without this, the last frame would render incorrectly
} else {
factor = this.ease(time, 0, 1, this.duration);
}
for (i = this.tweens.length - 1; i > -1; i--) {
tp = this.tweens[i];
tp[0][tp[1]] = tp[2] + (factor * tp[3]); //tween index values: [object, property, start, change, name]
}
if (_hst) { //has sub-tweens
for (i = _subTweens.length - 1; i > -1; i--) {
_subTweens[i].proxy(_subTweens[i]);
}
}
if (_hasUpdate) {
this.vars.onUpdate.apply(null, this.vars.onUpdateParams);
}
if (time == this.duration) {
complete(true);
}
}
public static function executeAll(skipRender:Boolean = false):void {
if (!t:@ax-lib-flex-animation-code-10-gs-TweenLite, t != null) {
if (t.clear();
}
target:Object = null, target != null && masterList[target], i:int, tween:@ax-lib-flex-animation-code-10-gs-TweenLite;
for (i = a.length - 1; i > -1; i--) {
tween = a[i];
if (target];
}
}
public function killVars(vars, this.vars, this.tweens, _subTweens, []);
}
}
public static function killGarbage(t:Number, c:Number, c * (d) * (b;
}
//---- PROXY FUNCTIONS ------------------------------------------------------------------------
protected function easeProxy(b:Number, d:Number):Number { //Just for when easeParams are passed in via the vars object.
return this.vars.proxiedEase.apply(null, arguments.concat(this.vars.easeParams));
}
public static function tintProxy(o.target.progress, r:Number = 1 - n, sc:Object = o.info.endColor;
o:Object):void {
o.target.frame));
}
public static function volumeProxy(o.info.target.soundTransform = b:Boolean):void {
if (b;
if (this.gc) {
this.forceActive = false;
} else {
this.forceActive = this.started;
}
}
}
}
(C) Æliens
19/08/2009
You may not copy or print any of this material without explicit permission of the author or the publisher.
In case of other copyright issues, contact the author.