package { import aeon.AnimationComposite; import aeon.AnimationHold; import aeon.AnimationLoop; import aeon.AnimationSequence; import aeon.animators.FilterAnimator; import aeon.animators.Transformer3D; import aeon.animators.Tweener; import aeon.easing.Back; import aeon.easing.Quad; import aether.utils.ImageUtil; import flash.display.Bitmap; import flash.display.BitmapData; import flash.display.Sprite; import flash.filters.GlowFilter; import flash.geom.Matrix3D; import flash.geom.Vector3D; import flash.text.TextField; import flash.text.TextFieldAutoSize; import flash.text.TextFormat; [SWF(width=600, height=400, backgroundColor=0x333333)] /** * Demonstrates how letters in a textfield can be separated into separate bitmap data instances * so that different effects may be applied to each. Here, each letter can be animated separately. */ public class graphic_flex_image_effects_09_Flex_TextAnimationEngine extends Sprite { private var _animations:Vector.; /** * Constructor. Creates textfield, draws each letter into separate bitmap data, * then kicks off animation of letters. */ public function graphic_flex_image_effects_09_Flex_TextAnimationEngine() { var field:TextField = createField(); var letters:Vector. = createLetterBitmaps(field); animateLetters(letters); } /** * Creates a textfield. * * @return The textfield created. */ private function createField():TextField { var field:TextField = new TextField(); // make sure you have Impact installed field.defaultTextFormat = new TextFormat("Impact", 100, 0xFFFFFF); field.autoSize = TextFieldAutoSize.LEFT; field.text = "ANIMATION"; field.x = (stage.stageWidth - field.width)/2; field.y = (stage.stageHeight - field.height)/2; return field; } /** * Draws each letter in textfield into separate bitmap data and returns * these references in a vector. * * @param field The textfield with text to draw into bitmap data instance. * * @return A vector of BitmapData instances where each instance holds the pixel * data from a single letter. */ private function createLetterBitmaps(field:TextField):Vector. { // draw entire field into bitmap data var bitmapData:BitmapData = ImageUtil.getBitmapData(field); var letters:Vector. = new Vector.(); var text:String = field.text; var numLetters:uint = field.text.length; // will be used to center vertically var halfHeight:Number = field.height/2; // the placement of the first letter var startX:Number = field.x; // the vertical middle of the field var y:Number = field.y + halfHeight; var x:Number; var letterData:BitmapData; var bitmap:Bitmap; var sprite:Sprite; var bitmapWidth:Number; for (var i:uint = 0; i < numLetters; i++) { // create a sprite to hold each bitmap sprite = new Sprite(); // place the single letter being evaluated into the field field.text = text.charAt(i); // draw the single letter into bitmap data letterData = ImageUtil.getBitmapData(field); bitmap = new Bitmap(letterData); // find width of letter bitmapWidth = bitmap.width; // center the letter horizontally on the bitmaps registration point bitmap.x = -bitmapWidth/2; // center the letter vertically on the bitmaps registration point bitmap.y = -halfHeight; // place all the text up to and including this letter into field field.text = text.substr(0, i+1); // based on field's current length and width of bitmap, place letter x = startX + field.width - bitmapWidth; sprite.x = x + bitmapWidth/2; sprite.y = y; // add bitmap to sprite and sprite to stage; // the nesting is done so that the sprite may be transformed with the bitmap centered within it sprite.addChild(bitmap); addChild(sprite); // push data into vector letters.push(sprite); } return letters; } /** * Animates the sprites in the vector. * * @param letters The letters to animate. */ private function animateLetters(letters:Vector.):void { // will be used to save the animations so they are not garbage collected _animations = new Vector.(); var endMatrix:Matrix3D; var startMatrix:Matrix3D; var animation:AnimationSequence; for (var i:uint = 0; i < letters.length; i++) { // set z so that each may be transformed in 3D space letters[i].z = 0; // each letter will start off at 0 alpha letters[i].alpha = 0; // the current letter position will be the end of the 3D transform endMatrix = letters[i].transform.matrix3D; // use the current transform as basis as start 3D transform startMatrix = endMatrix.clone(); startMatrix.prependRotation(120, Vector3D.Y_AXIS); startMatrix.prependRotation(90, Vector3D.Z_AXIS); startMatrix.appendTranslation(-50, 0, 0); // each letter will be animated in one long sequence animation = new AnimationSequence( [ // the sequence will start off with a hold so that each letter starts at different time new AnimationHold((i+1)*150), // the animation contained within this loop will play indefinitely new AnimationLoop( new AnimationSequence( [ // the looped sequence begins with a tween up of alpha and a 3D transform, run simultaneously new AnimationComposite( [ new Tweener(letters[i], {alpha:0}, {alpha:1}, 100), new Transformer3D( letters[i], startMatrix, endMatrix, 800, Quad.easeOut ) ] ), // wait for 800 ms new AnimationHold(800), // animate the GlowFilter up new FilterAnimator( letters[i], new GlowFilter(0x66FF66), {blurX:0, blurY:0}, {blurX:20, blurY:20}, -1, 400 ), // animate the GlowFilter down new FilterAnimator( letters[i], new GlowFilter(0x66FF66), {blurX:20, blurY:20}, {blurX:0, blurY:0}, -1, 400 ), // wait for another 800 ms new AnimationHold(800), // scale the letters up on the x axis, down on the y, while fading out new Tweener( letters[i], {scaleX:1, scaleY:1, alpha:1}, {scaleX:3, scaleY:0, alpha:0}, 400, Back.easeIn ), // hold for 2 seconds new AnimationHold(2000), // place letters back at full scale before starting again new Tweener( letters[i], {scaleX:1, scaleY:1}, {scaleX:1, scaleY:1}, 0 ) ] ) ) ] ) _animations.push(animation); animation.start() } } } }