📄 transitioner.as
字号:
package flare.animate
{
import flare.util.Property;
import flare.util.IValueProxy;
import flash.display.DisplayObject;
import flash.geom.Rectangle;
import flash.utils.Dictionary;
/**
* Parallel transition with convenience methods for adding new
* object tweens, helping to incrementally construct a group of transitions.
* A Transitioner will automatically generate tweens for any number of
* items and properties, simplifying the task of creating animated
* transitions.
*
* <p>For example, the following code creates a 1 second
* animation for two items. The first item is translated to the point
* (50,50) and the second item is scaled along the x dimension to twice the
* normal size.</p>
* <pre>
* var item1:Sprite, item2:Sprite; // assume these are two drawn sprites
* var t:Transitioner = new Transitioner(1); // create 1-second transition
* t.$(item1).x = 50;
* t.$(item1).y = 50;
* t.$(item2).scaleX = 2;
* t.play();
* </pre>
*
* <p>In the code above, the <code>$</code> method takes an item (this
* can be any ActionScript object, but is often a <code>DisplayObject</code>
* instance) and returns an <code>Object</code> which stores the names of
* the properties to animate and their target values. Behind the scenes,
* the <code>Transitioner</code> automatically creates <code>Tween</code>
* objects as needed.</p>
*
* <p>The object returned by the <code>$</code> method is a proxy object
* that passes the values to underlying tweens as needed. This same proxy
* object is reused across calls to the <code>$</code> method so do
* <strong>not</strong> attempt to use multiple return values from the
* <code>$</code> method simultaneously. <em>The following example shows
* what you should not do!</em></p>
* <pre>
* var o1:Object = t.$(item1);
* var o2:Object = t.$(item2); // o2==o1, now configured for item2
* o1.x = 5; // actually sets the value 5 to item2, NOT item1
* </pre>
*
* <p>
* A transitioner can also be set to "immediate" mode, either by setting
* the <code>immediate</code> property to true, or by passing in
* <code>NaN</code> as the duration value to the constructor. When in
* immediate mode, a transitioner will <strong>NOT</strong> generate
* <code>Tween</code> instances to animate the properties. Instead, the
* transitioner will set the values of the target objects immediately.
* For example, when in immediate mode, the <code>$</code> operator is
* equivalent to directly setting the property:
* <code>t.$(item1).x = 50</code> has exactly the same result at
* <code>t.x = 50</code>. The static property
* <code>Transitioner.DEFAULT</code> provides a default instance of an
* immediate-mode transitioner.
* </p>
*
* <p>
* With these features, transitioners provide a highly flexible way to
* update values in your application. You can write layout and other
* methods once, using a transitioner to update all the property values.
* When animation is desired, a standard transitioner can be passed in
* to your routines. When immediate updates are desired, you can reuse
* the same code, but just pass in a transitioner in immediate mode
* instead. Whether or not value updates are animated or immediate then
* becomes easy to control.
* </p>
*
* <p>
* Transitioners also provide optimizations to improve animation
* performance. However, they are not enabled by default, as the
* optimizations make some assumptions about how the transitioner will
* be used. See the <code>optimize</code> property and
* <code>dispose</code> method for more information.
* </p>
*/
public class Transitioner extends Parallel implements IValueProxy
{
/** The default, immediate-mode transitioner instance. */
public static const DEFAULT:Transitioner = new Transitioner(NaN);
/**
* Gets a transitioner instance depending upon the input value.
* @param t input determining the transitioner instance to return. If
* the input is a transitioner, it is simply returned. If the input is
* a number, a new Transitioner with duration set to the input value
* is returned, unless the number is less than zero, in which case the
* default immediate-mode transitioner is returned. If the input is
* null, <code>Transitioner.DEFAULT</code> is returned.
* @return a Transitioner instance determined by the input
*/
public static function instance(t:*):Transitioner {
if (t is Number) {
var dur:Number = Number(t);
return dur<0 ? Transitioner.DEFAULT : new Transitioner(dur);
} else if (t == null) {
return Transitioner.DEFAULT;
} else {
return t as Transitioner;
}
}
// --------------------------------------------------------------------
private var _immediate:Boolean;
private var _lookup:/*Object->Tween*/Dictionary = new Dictionary();
private var _proxy:ValueProxy;
private var _optimize:Boolean = false;
private var _subdur:Number;
/** @private */
public override function get duration():Number {
return _trans.length==0 ? _subdur : super.duration;
}
/** Immediate mode flag, used to bypass tween generation and perform
* immediate updates of target object values. */
public function get immediate():Boolean { return _immediate; }
public function set immediate(b:Boolean):void {
_immediate = b;
if (!immediate && _proxy == null) _proxy = new ValueProxy(this);
}
/**
* Flag indicating if aggressive optimization should be applied.
* This can significantly decrease processing time when large numbers
* of elements are involved. However, the optimization process makes a
* few assumptions about how the transitioner will be used. If these
* assumptions are not met, the animations may exhibit unexpected
* behaviors.
*
* <p>The assumptions made for optimized transitioners are:
* <ol>
* <li>The property values of tweened objects will not change between
* the time their target values are set and the transition is
* played. This allows the transitioner to avoid creating tweens
* when properties have the same starting and ending values, and
* immediately set values for DisplayObjects that are not visible.
* However, this means the starting value must stay the same. In
* particular, this means that optimized transitioners are often
* inappropriate for use within a <code>Sequence</code>.</li>
* <li>The transitioner will only be played once, then discarded.
* This allows the transitioner to automatically recycle all
* generated <code>Tween</code> and <code>Interpolator</code>
* instances, reducing initialization time across transitioners by
* reusing objects.</li>
* </ol>
* </p>
*/
public function get optimize():Boolean { return _optimize; }
public function set optimize(b:Boolean):void { _optimize = b; }
// --------------------------------------------------------------------
/**
* Creates a new Transitioner with specified duration.
* @param duration the length of the transition. If this value is NaN,
* the transitioner will be in immediate mode, in which all changes
* are immediately applied and no tweens are generated.
* @param easing the easing function to use for this transition. If
* null, the function Easing.none will be used.
* @param optimize boolean flag indicating if the transitioner should
* attempt to optimize tween construction. See the documentation
* for the <code>optimize</code> property for mode details.
* @param id an optional id. If non-null, any other running transition
* with the same id will be canceled when this transitioner is played.
*/
public function Transitioner(duration:Number=1, easing:Function=null,
optimize:Boolean=false, id:String=null)
{
super.easing = easing==null ? DEFAULT_EASING : easing;
_subdur = duration;
_optimize = optimize;
_immediate = isNaN(duration);
if (id!=null) this.id = id;
if (!_immediate) _proxy = new ValueProxy(this);
}
/**
* Indicates if the Transitioner contains a Tween for the given object.
* @param o the object to test for
* @return true if there is a Tween for the object, false otherwise
*/
public function hasTweenFor(o:Object):Boolean
{
return _immediate ? false : (_lookup[o] != undefined);
}
/**
* Returns the Tween for the given object, creating a new tween if no
* tween is yet associated with the object. This method returns null if
* the transitioner is in immediate mode.
* @param o the target object
* @return a tween for the input target object, or null if this
* transitioner is in immediate mode.
*/
public function _(o:Object):Tween
{
if (_immediate) return null;
var tw:Tween = _lookup[o];
if (tw == null) {
add(tw = getTween(o, _subdur));
tw.easing = Easing.none;
_lookup[o] = tw;
}
return tw;
}
/**
* Returns the values object of the Tween for the given object. If no
* tween is associated with the object, a new one is created.
*
* If the transitioner is in immediate mode, then no Tween will be
* created. Instead, the input object will be returned. This allows
* value updates to be set immediately, rather than animated by a
* tween.
* @param o the target object
* @return the <code>values</code> object for the target object's
* tween, or the target object itself if this transitioner is in
* immediate mode.
*/
public function $(o:Object):Object
{
return _immediate ? o : _proxy.init(o);
}
/**
* Sets property values for a target object. This method has the same
* effect as setting a property on the object returned by the
* <code>$</code> method.
*
* <p>If the transitioner is in immediate mode, the property name will
* be parsed and the value set at the end of the property chain. If
* the transitioner is not in immediate mode, the property name and
* values will simply be added to a Tween. If no Tween is associated
* with the input object, a new one will be created.</p>
*
* @param o the target object
* @param name the property name string
* @param value the property value to set
*/
public function setValue(o:Object, name:String, value:*):void
{
if (_immediate) {
// set the object property
Property.$(name).setValue(o, value);
} else if (optimize && getValue(o, name) == value) {
// do nothing, optimize the call away...
} else if (optimize && o is DisplayObject && !getValue(o, "visible")) {
Property.$(name).setValue(o, value);
} else {
// add to a tween
_(o).values[name] = value;
}
}
/**
* Retrieves property values for a target object. This method has the
* same effect as accessing a property using the object returned by the
* <code>$</code> method.
*
* <p>If the transitioner is in immediate mode, the property name will
* be parsed and the value retrieved diretly from the target object. If
* the transitioner is not in immediate mode, this method will first
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -