/* CASA Framework for ActionScript 3.0 Copyright (c) 2008, Contributors of CASA Framework All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - Neither the name of the CASA Framework nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.casaframework.transitions { import flash.events.Event; import flash.events.EventDispatcher; import org.casaframework.events.TweenEvent; import org.casaframework.math.Percent; import org.casaframework.time.EnterFrame; import org.casaframework.time.FrameTimeStopwatch; [Event(name="start", type="org.casaframework.events.TweenEvent")] [Event(name="stop", type="org.casaframework.events.TweenEvent")] [Event(name="resume", type="org.casaframework.events.TweenEvent")] [Event(name="update", type="org.casaframework.events.TweenEvent")] [Event(name="complete", type="org.casaframework.events.TweenEvent")] /** Simple and easily extendable tween/transition class. Advantages of using this tween class over others:
package {
import fl.motion.easing.Bounce;
import flash.display.MovieClip;
import org.casaframework.events.TweenEvent;
import org.casaframework.transitions.Tween;
public class MyExample extends MovieClip {
protected var _tween:Tween;
public function MyExample() {
super();
this._tween = new Tween(Bounce.easeOut, 0, 1, 2);
this._tween.addEventListener(TweenEvent.UPDATE, this._onTweenPosition);
this._tween.start();
}
protected function _onTweenPosition(e:TweenEvent):void {
trace(e.position);
}
}
}
You can tween color by using {@link ColorUtil}'s {@link ColorUtil#interpolateColor interpolateColor} function:
package {
import fl.motion.easing.Linear;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.geom.ColorTransform;
import org.casaframework.events.TweenEvent;
import org.casaframework.transitions.Tween;
import org.casaframework.util.ColorUtil;
public class MyExample extends MovieClip {
protected var _box:Sprite;
protected var _finishColor:ColorTransform;
protected var _tween:Tween;
public function MyExample() {
super();
this._box = new Sprite();
this._box.graphics.beginFill(0x0000FF);
this._box.graphics.drawRect(0, 0, 250, 250);
this._box.graphics.endFill();
this.addChild(this._box);
this._finishColor = new ColorTransform();
this._finishColor.color = 0xFF0000;
this._tween = new Tween(Linear.easeOut, 0, 1, 1);
this._tween.addEventListener(TweenEvent.UPDATE, this._onTweenPosition);
this._tween.start();
}
protected function _onTweenPosition(e:TweenEvent):void {
this._box.transform.colorTransform = ColorUtil.interpolateColor(new ColorTransform(), this._finishColor, e.progress);
}
}
}
If you want to tween an item on a ellipse you can use the {@link Ellipse} class and its {@link Ellipse#getPointOfDegree getPointOfDegree} function:
package {
import fl.motion.easing.Bounce;
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.geom.Point;
import org.casaframework.events.TweenEvent;
import org.casaframework.math.geom.Ellipse;
import org.casaframework.transitions.Tween;
public class MyExample extends MovieClip {
protected var _box:Sprite;
protected var _tween:Tween;
protected var _ellipse:Ellipse = new Ellipse(20, 50, 300, 200);
public function MyExample() {
super();
this._box = new Sprite();
this._box.graphics.beginFill(0xFF00FF);
this._box.graphics.drawRect(0, 0, 25, 25);
this._box.graphics.endFill();
this.addChild(this._box);
this._tween = new Tween(Bounce.easeOut, 0, 360, 5);
this._tween.addEventListener(TweenEvent.UPDATE, this._onTweenPosition);
this._tween.start();
}
protected function _onTweenPosition(e:TweenEvent):void {
var point:Point = this._ellipse.getPointOfDegree(e.position);
this._box.x = point.x;
this._box.y = point.y;
}
}
}
@usageNote If you want to tween a property use {@link PropertyTween}.
@see {@link PropertySetter}
*/
public class Tween extends EventDispatcher {
protected var _complete:Boolean;
protected var _equat:Function;
protected var _frameFires:Number;
protected var _framePulse:EnterFrame;
protected var _stopped:Boolean;
protected var _stopwatch:FrameTimeStopwatch;
protected var _time:Number;
protected var _useFrames:Boolean;
protected var _begin:Number;
protected var _currentPosition:Number;
protected var _diff:Number;
protected var _end:Number;
/**
Creates and defines a new Tween.
@param equation: The tween equation.
@param startPos: The starting value of the transition.
@param endPos: The ending value of the transition.
@param duration: Length of time of the transition.
@param useFrames: Indicates to use frames {@code true}, or seconds {@code false} in relation to the value specified in the duration parameter.
@usageNote The function specified in the equation parameter must follow the (currentTime, startPosition, endPosition, totalTime) parameter standard.
*/
public function Tween(equation:Function, startPos:Number, endPos:Number, duration:Number, useFrames:Boolean = false) {
super();
this._equat = equation;
this._begin = this.position = startPos;
this._end = endPos;
this._diff = this._end - this._begin;
this._time = duration;
this._useFrames = useFrames;
if (!this._useFrames) {
this._time *= 1000;
this._stopwatch = new FrameTimeStopwatch();
}
this._framePulse = EnterFrame.getInstance();
this._stopped = true;
}
/**
Starts the transition from its starting position.
@sends TweenEvent#START - Dispatched when transition starts.
*/
public function start():void {
if (this._useFrames)
this._frameFires = 0;
else
this._stopwatch.start();
this._stopped = this._complete = false;
this._framePulse.addEventListener(Event.ENTER_FRAME, this._onFrame);
var updateEvent:TweenEvent = new TweenEvent(TweenEvent.START);
updateEvent.progress = this.progress;
updateEvent.position = this.position;
this.dispatchEvent(updateEvent);
}
/**
Stops the transition at its current position.
@sends TweenEvent#STOP - Dispatched when transition is stopped.
*/
public function stop():void {
if (!this.tweening || this.complete)
return;
this._stopped = true;
if (!this._useFrames)
this._stopwatch.stop();
this._framePulse.removeEventListener(Event.ENTER_FRAME, this._onFrame);
var updateEvent:TweenEvent = new TweenEvent(TweenEvent.STOP);
updateEvent.progress = this.progress;
updateEvent.position = this.position;
this.dispatchEvent(updateEvent);
}
/**
Resumes the transition from {@link Tween#stop stopped} position.
@sends TweenEvent#START - Dispatched when transition is resumed.
*/
public function resume():void {
if (this.tweening || this.complete)
return;
this._stopped = false;
if (!this._useFrames)
this._stopwatch.resume();
this._framePulse.addEventListener(Event.ENTER_FRAME, this._onFrame);
var updateEvent:TweenEvent = new TweenEvent(TweenEvent.RESUME);
updateEvent.progress = this.progress;
updateEvent.position = this.position;
this.dispatchEvent(updateEvent);
}
/**
Transitions from the tween's current position to a new end position and duration.
@param endPos: The ending value of the transition.
@param duration: Length of time of the transition.
@usageNote Will automatically start tween if currently stopped.
*/
public function continueTo(endPos:Number, duration:Number):void {
this._begin = this.position;
this._end = endPos;
this._diff = this._end - this._begin;
this._time = (this._useFrames) ? duration : duration * 1000;
this.start();
}
/**
Determines if the Tween is currently transitioning {@code true}, or if it's still {@code false}.
*/
public function get tweening():Boolean {
return !this._stopped;
}
/**
Determines if Tween has completed the transition {@code true}, or if it hasn't {@code false}.
*/
public function get complete():Boolean {
return this._complete;
}
/**
The current position of the tween.
*/
public function get position():Number {
return this._currentPosition;
}
public function set position(pos:Number):void {
this._currentPosition = pos;
}
/**
The percent completed of the tween's duration.
*/
public function get progress():Percent {
return new Percent(this._timeProgress / this._time);
}
/**
@sends TweenEvent#UPDATE - Dispatched as the transition progresses.
@sends TweenEvent#COMPLETE - Dispatched when transition completes.
*/
protected function _onFrame(e:Event):void {
var finished:Boolean = false;
var timePos:Number = this._timeProgress;
var duration:Number = this._time;
if (timePos >= duration) {
if (duration == 0)
duration = 1;
timePos = duration;
finished = true;
}
this.position = this._equat(timePos, this._begin, this._diff, duration);
var updateEvent:TweenEvent = new TweenEvent(TweenEvent.UPDATE);
updateEvent.progress = this.progress;
updateEvent.position = this.position;
this.dispatchEvent(updateEvent);
if (finished) {
if (!this._useFrames)
this._stopwatch.stop();
this._framePulse.removeEventListener(Event.ENTER_FRAME, this._onFrame);
this._stopped = this._complete = true;
updateEvent = new TweenEvent(TweenEvent.COMPLETE);
updateEvent.progress = this.progress;
updateEvent.position = this.position;
this.dispatchEvent(updateEvent);
}
}
protected function get _timeProgress():Number {
if (this._useFrames)
return ++this._frameFires;
else
return this._stopwatch.time;
}
}
}