An Example and the Code

In this How-To, we show how to create a simple image reflection that can be rotated in 3D. We use a gradient mask and the 3D methods available in Flash Player 10 to accomplish the effect. For a discussion of gradient masks see another of our How - Tos: How to Create a Gradient Mask in ActionScript 3. For a simple reflection without rotation, see: How to Create a Simple Image Reflection in AS3.

Download

The Code

We keep comments as comments within the code for greater clarity.

Note: For exporting Flash Library assets to AS3, you may want to check out another How - To: How to Link Library Items to AS3 in Flash CS4 and CS3 for Runtime Use.

/*
We have imported to the Library a 160 by 160 jpeg image, shuttle160m.jpg. Using the Properties - Linkage item in the Library menu, we exported the image to AS3 under the class name 'Shuttle'.
*/

var picWidth:Number=160;

var picHeight:Number=160;

//The gap, in pixels betwen the image and its reflection.

var gap:Number=1;

var goLeft:Boolean=false;

var goRight:Boolean=false;

/*
'Shuttle' is a BitmapData object which can be instantiated at runtime. This is what we are doing in the next line. Then we create two Bitmaps, 'topImg' and 'reflImg', to hold the image and its reflection, repectively.
*/

var imgBD:BitmapData=new Shuttle(160,160);

var topImg:Bitmap=new Bitmap(imgBD);

var reflImg:Bitmap=new Bitmap(imgBD);

/*
Since we want to rotate the image and its reflection about a vertical axis through the center of both images, we create containers topCont and reflCont and position the images in those containers so the registration point is in the center. Since we want the whole assembly to have its own perspective projection, we create a container for both containers, ppCont.
*/

var topCont:Sprite=new Sprite();

var reflCont:Sprite=new Sprite();

var ppCont:Sprite=new Sprite();

this.addChild(ppCont);

topCont.addChild(topImg);

topImg.x=-picWidth/2;

topImg.y=-picHeight/2;

reflCont.addChild(reflImg);

reflImg.x=-picWidth/2;

reflImg.y=-picHeight/2;

//We flip the reflected image about the x axis.

reflCont.rotationX=180;

ppCont.addChild(topCont);

topCont.x=picWidth/2;

topCont.y=picHeight/2;

topCont.z=0;

ppCont.addChild(reflCont);

reflCont.x=topCont.x;

reflCont.y=topCont.y+picHeight+gap;

reflCont.z=0;

var pp:PerspectiveProjection=new PerspectiveProjection();

pp.fieldOfView=55;

pp.projectionCenter=new Point(picWidth/2,picHeight/2);

ppCont.transform.perspectiveProjection=pp;

/*
We placed the projection center for ppCont in the center of the top image. if you change the x and y positon of ppCont, the projection center will not be affected. If, however, you apply any of the 3D methods to ppCont, for example assign a value to its z-coordinate, the projection center will move to the center of the Stage. If you want to change the z-position of ppCont, change the z-coordinate of topCont and reflCont.
*/

/*
We position the top image 80 pixels above the center of the Stage.
*/

ppCont.x=250-picWidth/2;

ppCont.y=220-picHeight/2-80;

/*
In order to create a gradient effect for the reflection, we will create a gradient mask for 'reflImg'.
*/

var maskingShape:Shape=new Shape();

 

//Even though the mask itself will not be visible,

//it MUST be added to the Display List.

 

reflCont.addChild(maskingShape);

maskingShape.x=reflImg.x;

maskingShape.y=reflImg.y;

 

//We call a function, defined later in the script,

//that draws a gradient in 'maskingShape'.

 

drawInMask();

/*
The next two lines are crucial for a gradient mask to bahave properly: both a masked Display Object and a masking Display Object must be cached as Bitmaps. Otherwise, the whole area of the gradient (except for the completely transparent areas) will fully reveal the underlying image, and the gradient effect will not happen.
*/

reflImg.cacheAsBitmap=true;

maskingShape.cacheAsBitmap=true;

 

//We assign 'maskingShape' to be a mask of 'reflImg'.

 

reflImg.mask=maskingShape;

/*
The function defined below draws a linear gradient in 'maskingShape'. If you wish to see the gradient, comment out the line above. You see a linear gradient that goes from transparent red to full red, rotated 90 degrees. The rotation happens within the gradient box:
    mat.createGradientBox(picWidth,picHeight,90*(Math.PI/180));
90 degress is converted to radians: 90*(Math.PI/180).
*/

function drawInMask():void {

var mat:Matrix= new Matrix();

var colors:Array=[0xFF0000,0xFF0000];

var alphas:Array=[0,0.7];

var ratios:Array=[10,255];

mat.createGradientBox(picWidth,picHeight,90*(Math.PI/180));

maskingShape.graphics.lineStyle();

maskingShape.graphics.beginGradientFill(GradientType.LINEAR,colors,alphas,ratios,mat);

maskingShape.graphics.drawRect(0,0,picWidth,picHeight);

maskingShape.graphics.endFill();

}

/*
We attach listeners to our buttons. Those listeners combined we the ENTER_FRAME listener below, will create rotation.
*/

btnLeft.addEventListener(MouseEvent.ROLL_OVER,leftOn);

 

function leftOn(e:MouseEvent):void {

goLeft=true;

}

 

btnLeft.addEventListener(MouseEvent.ROLL_OUT,leftOff);

 

function leftOff(e:MouseEvent):void {

goLeft=false;

}

 

btnRight.addEventListener(MouseEvent.ROLL_OVER,rightOn);

 

function rightOn(e:MouseEvent):void {

goRight=true;

}

 

btnRight.addEventListener(MouseEvent.ROLL_OUT,rightOff);

 

function rightOff(e:MouseEvent):void {

goRight=false;

}

 

this.addEventListener(Event.ENTER_FRAME,onEnter);

 

function onEnter(e:Event):void {

if(goLeft){

topCont.rotationY+=4;

reflCont.rotationY+=4;

}

if(goRight){

topCont.rotationY+=-4;

reflCont.rotationY+=-4;

}

}

 

The reason for the 2D conatiner 'ppCont' in the script above is the behavior of the PerspectiveProjection object when applied to 2D versus 3D containers. See our tutorial: How to Set Perspective Projection of Display Objects - Experiments in Flash CS4. for in-depth discussion of this issue.

How to Customize Reflection

Since a gradient mask simply makes the masked object invisible in the areas where the gradient is transparent, what shows through is whatever is behind the reflection. In our case, it is the black background. Other properties can be customized by changing a few variables in 'drawInMask' function.

There are two variables within 'drawInMask' function that you can manipulate in order to easily change the appearance of the reflection: alphas and ratios. Each element in 'alphas' Array has to be a number between 0 and 1. Try changing:

var alphas:Array=[0,0.7];

to:

var alphas:Array=[0,1];

or to:

var alphas:Array=[0,0.5];

and observe the changes as you test the movie.

Each element in 'ratios' Array has to be a number between 0 and 255. Try changing:

var ratios:Array=[10,255];

to:

var ratios:Array=[100,255];

or to:

var ratios:Array=[0,100];

and observe the changes as you test the movie.

Back to AS3 How To and Tips              Back to Flash and Math Home

We welcome your comments, suggestions, and contributions. Click the Contact Us link below and email one of us.

Adobe®, Flash®, ActionScript®, Flex® are registered trademarks of Adobe Systems Incorporated.