/** Sparkle Text Tronster - http://tronster.com Inspired from Reebok's "Defy convention" commericals in 2006 */ package { import flash.display.*; import flash.events.*; import flash.geom.*; import flash.text.*; import flash.utils.getTimer; import flash.filters.*; [SWF(backgroundColor="#000000", frameRate=61)] public class SparkleClass extends Sprite { /// CHANGE THIS: What do you want to display. private const msg:String = "DEFY"; /// CHANGE THIS: to make the individual sparkles bigger/smaller: private const SPARKLE_SIZE :int = 16; /// CHANGE THIS: to increase/decrease space between sparkles. private const SPARKLE_PADDING : int = 2; /// CHANGE THIS: Amount of a pixel's opacity to be considered a sparkle [0-255]. private const PIXEL_OPACITY_THRESHOLD: int = 128; /// CHANGE THIS: Size of font. private const sparkleFontHeight :int = 28; /// Computed based on height. private var sparkleFontWidth :int; /// Holds raw sampled data from rasterized text on bitmap. private var sparkleData :Vector.<uint>; // Holds actual sparkle. private var sparkles:Vector.<Shape>; // Holds an initial random value for sparkle. private var sparklesRandom:Vector.<Number>; /// Ctor public function SparkleClass() { // Allocate sparkles and their randoms. sparkles = new Vector.<Shape>(); sparklesRandom = new Vector.<Number>(); // Holds rasterized text. var bitmap:Bitmap; var tf:TextField = new TextField(); var fmt:TextFormat = new TextFormat("Arial", 64, 0xFFFFFF, true); tf.defaultTextFormat = fmt; tf.autoSize = TextFieldAutoSize.LEFT; tf.text = msg; //addChild( tf ); var bmpData:BitmapData = new BitmapData(tf.textWidth, tf.textHeight, true, 0x000000); bmpData.draw( tf, new Matrix() ); bitmap = new Bitmap( bmpData ); //addChild( bitmap ); bitmap.y = 50; var ratio :Number = sparkleFontHeight / tf.textHeight; sparkleFontWidth = int(ratio * tf.width ); trace( " tf.w,tf.h: " + tf.textWidth + " x " + tf.textHeight ); trace( " w,h: " + tf.width + " x " + tf.height); trace( " ratio: " + ratio ); trace( " sparkle: " + sparkleFontWidth + " x " + sparkleFontHeight ) ; // Fill vector with sampling of pixels sparkleData = new Vector.<uint>( sparkleFontWidth * sparkleFontHeight ); for (var iy:int = 0; iy < sparkleFontHeight; iy++ ) { for (var ix:int = 0; ix < sparkleFontWidth; ix++ ) { sparkleData[ix + (iy * sparkleFontWidth)] = bmpData.getPixel32(ix * (1/ratio),iy * (1/ratio)); } } addEventListener( Event.ADDED_TO_STAGE, onAddedToStage ); } /// This is on the stage; wire listeners. private function onAddedToStage( e:Event ):void { removeEventListener( Event.ADDED_TO_STAGE, onAddedToStage ); // Holds sampling in a string to send to output. var debugSampling:String =""; var pixel:uint; for (var iy:int = 0; iy < sparkleFontHeight; iy++ ) { for (var ix:int = 0; ix < sparkleFontWidth; ix++ ) { pixel = sparkleData[ix + (iy * sparkleFontWidth)]; // Flash bug?: If the last AND is not performed then sometimes // the first bit (negative) stays set. var pixelA:uint = (( pixel & 0xff000000 ) >> 24) & 0xff; if ( pixelA > PIXEL_OPACITY_THRESHOLD ) { debugSampling += "#"; addSparkle(ix, iy); } else debugSampling += "-"; } debugSampling += "\n"; } trace( debugSampling ); // Glow & blur to add organic goodness! filters = [ new BlurFilter(1.5,1.5,3), new GlowFilter(0xffffff,0.9,8,8,2,3) ]; addEventListener( Event.ENTER_FRAME, onFrame ); } /// Adds a sparkle private function addSparkle(ix:int, iy:int) :void { // Create and add to display list. var shape:Shape = new Shape(); shape.x = ix * (SPARKLE_SIZE + SPARKLE_PADDING); shape.y = iy * (SPARKLE_SIZE + SPARKLE_PADDING); addChild( shape ); // Add to our own list (for easy updates later). sparkles.push( shape ); // Generate a random # to associate with this sparkle. sparklesRandom.push( Math.random() * 123 ); } /// Update a sparkle private function updateSparkle( offset:int, time:int ) { var intensity:Number; intensity = 0.25 + ( ((Math.sin( sparklesRandom[offset] + (time*0.005) ) + 1) * 0.5) * 0.75 ); var shape:Shape = sparkles[offset]; shape.graphics.clear(); shape.graphics.beginFill( 0xd0e0ff, intensity ); shape.graphics.drawRect(0, 0, SPARKLE_SIZE, SPARKLE_SIZE); shape.graphics.endFill(); } /// Called once a frame private function onFrame( e:Event ):void { var time:int = getTimer(); var len:int = sparkles.length; for(var offset:int = 0; offset < len; ++offset) updateSparkle( offset, time ); // ???TMH - This .x is hard coded for a four letter word. //this.x = Math.sin( time * 0.001 ) * -1000; this.x = -400; this.z = 50 - Math.sin( time * 0.001 ) * 700; } } } Sparkle Text