📄 gtweentimeline.as
字号:
/*** GTweenTimeline by Grant Skinner. Jan 15, 2009* Visit www.gskinner.com/blog for documentation, updates and more free code.*** Copyright (c) 2009 Grant Skinner* * Permission is hereby granted, free of charge, to any person* obtaining a copy of this software and associated documentation* files (the "Software"), to deal in the Software without* restriction, including without limitation the rights to use,* copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the* Software is furnished to do so, subject to the following* conditions:* * The above copyright notice and this permission notice shall be* included in all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR* OTHER DEALINGS IN THE SOFTWARE.**/package com.gskinner.motion { import com.gskinner.motion.GTween; import flash.utils.Dictionary; /** * <b>GTweenTimeline ©2008 Grant Skinner, gskinner.com. Visit www.gskinner.com/libraries/gtween/ for documentation, updates and more free code. Licensed under the MIT license - see the source file header for more information.</b> * <hr> * GTweenTimeline is a powerful sequencing engine for GTween. It allows you to build a virtual timeline * with tweens, actions (callbacks), and labels. It supports all of the features of GTween, so you can repeat, * reverse, and pause the timeline. You can even embed timelines within each other. GTweenTimeline adds about 1kb above GTween. */ public class GTweenTimeline extends GTween { // static properties: /** * Sets a property value on a specified target object. This is provided to make it easy to set properties * in a GTweenTimeline using <code>addCallback</code>. For example, to set the <code>visible</code> property to true on a movieclip "foo" * at 3 seconds into the timeline, you could use the following code:<br/> * <code>myTimeline.addCallback(3,GTweenTimeline.setPropertyValue,[foo,"visible",true]);</code> * @param target The object to set the property value on. * @param propertyName The name of the property to set. * @param value The value to assign to the property. **/ public static function setPropertyValue(target:Object,propertyName:String,value:*):void { target[propertyName] = value; } // private properties: /** @private **/ protected var callbacks:Array; /** @private **/ protected var callbackPositions:Array; /** @private **/ protected var labels:Object; /** @private **/ protected var tweens:Array; /** @private **/ protected var tweenStartPositions:Array; // construction: /** * Constructs a new GTweenTimeline instance. * * @param target The object whose properties will be tweened. Defaults to null. * @param duration The length of the tween in frames or seconds depending on the timingMode. Defaults to 10. * @param properties An object containing destination property values. For example, to tween to x=100, y=100, you could pass <code>{x:100, y:100}</code> as the props object. * @param tweenProperties An object containing properties to set on this tween. For example, you could pass <code>{ease:myEase}</code> to set the ease property of the new instance. This also provides a shortcut for setting up event listeners. See .setTweenProperties() for more information. * @param tweens An array of alternating start positions and tween instances. For example, the following array would add 3 tweens starting at positions 2, 6, and 8: <code>[2, tween1, 6, tween2, 8, tween3]</code> **/ public function GTweenTimeline(target:Object=null, duration:Number=10, properties:Object=null, tweenProperties:Object=null, tweens:Array=null):void { super(target, duration, properties, tweenProperties); this.tweens = []; tweenStartPositions = []; callbacks = []; callbackPositions = []; labels = {}; addTweens(tweens); // unlike GTween, which waits for a setProperty to start playing, GTweenTimeline starts immediately: if (autoPlay) { paused = false; } } // public getter / setters: /** * Returns the label at the current position, or the previous label irrespective of whether the tween is playing forwards or backwards. For example, * if there are labels at 2, 4, and 7, and the current position is 6, the <code>currentLabel</code> will be the label at position 4. **/ public function get currentLabel():String { var minDelta:Number=duration+1; var label:String; for (var n:String in labels) { var delta:Number = labels[n]-_tweenPosition; if (delta >= 0 && delta < minDelta) { label = n; } } return label; } // public methods: /** * Adds a tween to the timeline, which will start playing at the specified start position. * The tween will play synchronized with the timeline, with all of its behaviours intact (ex. <code>reversed</code>, <code>repeat</code>, <code>reflect</code>) * except for <code>delay</code> (which is accomplished with the <code>startPosition</code> parameter instead). * * @param startPosition The starting position for this tween in frames or seconds (as per the timing mode of this tween). * @param tween The GTween instance to add. Note that this can be any subclass of GTween, including another GTweenTimeline. **/ public function addTween(startPosition:Number,tween:GTween):void { if (tween == null || isNaN(startPosition)) { return; } tween.autoPlay = false; tween.paused = true; var index:int = -1; while (++index < tweens.length && tweenStartPositions[index] < startPosition) { } tweens.splice(index,0,tween); tweenStartPositions.splice(index,0,startPosition); tween.position = _tweenPosition-startPosition; } /** * Shortcut method for adding a number of tweens at once. * * @param tweens An array of alternating start positions and tween instances. For example, the following array would add 3 tweens starting at positions 2, 6, and 8: <code>[2, tween1, 6, tween2, 8, tween3]</code> **/ public function addTweens(tweens:Array):void { if (tweens == null) { return; } for (var i:uint=0; i<tweens.length; i+=2) { addTween(tweens[i],tweens[i+1] as GTween); } } /** * Removes the specified tween. Note that this will remove all instances of the tween * if has been added multiple times to the timeline. * * @param tween The GTween instance to remove. **/ public function removeTween(tween:GTween):void { for (var i:int=tweens.length; i>=0; i--) { if (tweens[i] == tween) { tweens.splice(i,1); tweenStartPositions.splice(i,1); } } } /** * Adds a label at the specified position. You can use <code>gotoAndPlay</code> or <code>gotoAndStop</code> to jump to labels you add, * or use <code>currentLabel</code> to check what the last label you passed was. * * @param tween The position to add the label at in frames or seconds (as per the timing mode of this tween). * @param label The label to add. **/ public function addLabel(position:Number,label:String):void { labels[label] = position; } /** * Removes the specified label. * * @param label The label to remove. **/ public function removeLabel(label:String):void { delete(labels[label]); } /** * Adds a callback function at the specified position. When the timeline's playhead passes over or lands on the position while playing * the callback will be called with the parameters specified. Callbacks will not be called when manually adjusting the position using the position * property (see position for more information). * <br/><br/> * Note that this can be used in conjunction with the static <code>setPropertyValue</code> method to easily set properties on objects in the timeline. * * @param tween The position to add the callback at in frames or seconds (as per the timing mode of this tween). * @param label The function to call. * @param parameters Optional array of parameters to pass to the callback when it is called. **/ public function addCallback(position:Number,callback:Function,parameters:Array=null):void { var l:int = callbacks.length; for (var i:int = l-1; i>=0; i--) { if (position == callbackPositions[i]) { callbacks[i] = {callback:callback,parameters:parameters}; return; } if (position > callbackPositions[i]) { break; } } callbacks.splice(i+1,0,{callback:callback,parameters:parameters}); callbackPositions.splice(i+1,0,position); } /** * Removes the callback at the specified position. * * @param tween The position of the callback to remove in frames or seconds (as per the timing mode of this tween). **/ public function removeCallback(position:Number):void { var l:int = callbacks.length; for (var i:int = 0; i<l; i++) { if (position == callbackPositions[i]) { callbacks.splice(i,1); callbackPositions.splice(i,1); return; } } } /** * Jumps the timeline to the specified label or numeric position and plays it. * * @param labelOrPosition The label name or numeric position in frames or seconds (as per the timing mode of this tween) to jump to. **/ public function gotoAndPlay(labelOrPosition:*):void { goto(labelOrPosition); paused = false; } /** * Jumps the timeline to the specified label or numeric position and pauses it. * * @param labelOrPosition The label name or numeric position in frames or seconds (as per the timing mode of this tween) to jump to. **/ public function gotoAndStop(labelOrPosition:*):void { goto(labelOrPosition); paused = true; } /** * Jumps the timeline to the specified label or numeric position without affecting its paused state. * * @param labelOrPosition The label name or numeric position in frames or seconds (as per the timing mode of this tween) to jump to. **/ public function goto(labelOrPosition:*):void { if (!isNaN(labelOrPosition)) { position = labelOrPosition; } else { var pos:Number = labels[String(labelOrPosition)]; if (!isNaN(pos)) { position = pos; } } } /** * Calculates the duration of the timeline based on the tweens and callbacks that have been added to it. **/ public function calculateDuration():void { var d:Number = 0; if (callbacks.length > 0) { d = callbackPositions[callbacks.length-1]; } for (var i:int=0; i<tweens.length; i++) { if (tweens[i].duration+tweenStartPositions[i] > d) { d = tweens[i].duration+tweenStartPositions[i]; } } duration = d; } override public function setPosition(value:Number,suppressEvents:Boolean=true):void { super.setPosition(value,suppressEvents); // update tweens: var repeatIndex:Number = _position/duration>>0; var rev:Boolean = (reflect && repeatIndex%2>=1) != _reversed; var i:int; var l:int = tweens.length; if (rev) { for (i=0; i<l; i++) { tweens[i].setPosition(_tweenPosition-tweenStartPositions[i],false); } } else { for (i=l-1; i>=0; i--) { tweens[i].setPosition(_tweenPosition-tweenStartPositions[i],false); } } if (!suppressEvents) { checkCallbacks(); } } // protected methods: // checks for callbacks between the previous and current position (inclusive of current, exclusive of previous). /** @private **/ protected function checkCallbacks():void { if (callbacks.length == 0) { return; } var repeatIndex:Number = _position/duration>>0; var previousRepeatIndex:Number = _previousPosition/duration>>0; var matches:Array; if (repeatIndex == previousRepeatIndex) { checkCallbackRange(_previousTweenPosition, _tweenPosition); } else { // GDS: this doesn't currently support multiple repeats in one tick (ie. more than a single repeat). var rev:Boolean = (reflect && previousRepeatIndex%2>=1) != _reversed; checkCallbackRange(_previousTweenPosition, rev ? 0 : duration); rev = (reflect && repeatIndex%2>=1) != _reversed; checkCallbackRange(rev ? duration : 0, _tweenPosition, !reflect); } } // checks for callbacks between a contiguous start and end position (ie. not broken by repeats). /** @private **/ protected function checkCallbackRange(startPos:Number,endPos:Number,includeStart:Boolean=false):void { var sPos:Number = startPos; var ePos:Number = endPos; var i:int = -1; var j:int = callbacks.length; var k:int = 1; if (startPos > endPos) { // running backwards, flip everything: sPos = endPos; ePos = startPos; i = j; j = k = -1; } while ((i+=k) != j) { var pos:Number = callbackPositions[i]; if ( (pos > sPos && pos < ePos) || (pos == endPos) || (includeStart && pos == startPos) ) { callbacks[i].callback.apply(this,callbacks[i].parameters); } } } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -