The Effect and Code

This How-To is in response to a flashandmath.com reader who liked our magnifying glass effect for a bitmap image, Magnifying Glass Effect in Flash CS3 and AS3, but wanted to apply the same effect to a MovieClip object with vector graphics and text.

Download

Download the well-commented source file corresponding to the applet above, clipzoom.fla.

The General Idea

To implement this example we follow a line of reasoning from "How to Zoom In on a Point in an Image and Pan in AS3 Flash" -- we still use two copies of the thing we wish to enlarge, one that stays in the background (mcBack) and one that is scaled-up in the foreground (mcFront). However, there are two major differences: in the current example we use a mask (representing the magnifying glass)on the mcFront clip so that only part is visible; and in the current example we manage the scaling transformation directly rather than using the MatrixTransformer class.

To illustrate the effect we have made a simple MovieClip using drawing tools and the Text tool in the Flash IDE. Once drawn, we use "Modify > Convert to MovieClip" and name it PictureClip with its registration point at the top left and with the "Export for ActionScript" checkbox selected. This creates a class which we called PictureClip that we can use from within ActionScript. The instance of this class that is on the stage can be subsequently deleted, so in the source (fla) file that you download for this example, you will find PictureClip only in the Library, and not on the stage.

The Code

Below is commented code behind our zooming example.

var mcFront:PictureClip = new PictureClip();

var mcBack:PictureClip = new PictureClip();

 

// The width and height of the board should match the picture.

var boardWidth:int=mcBack.width;

var boardHeight:int=mcBack.height;

 

// Magnification factor

var scaleFactor:Number = 3;

 

// Helper variable to manage dragging motion of the magnifying glass.

var isMoving:Boolean = false;

The Sprite board provides a background on which the image resides. This serves no purpose other than containing all of the relevant interactive items so that they can be easily placed and moved on the stage.

var board:Sprite=new Sprite();

addChild(board);

 

//The size of the magnifying glass. You can change the values as you wish.

var glassWidth:int=150;

var glassHeight:int=150;

 

//The position of board determines the position of the picture within the main movie.

board.x=70;

board.y=90;

 

//Add the mcBack "background" version of the MovieClip as the first child of the board.

board.addChild(mcBack);

We think of spTopPlate like a "transparency slide" on which we will place the top copy (mcFront) of the MovieClip and the 'magnifying glass' and frame. We do this so that we can move the magnifying glass relative to the (unscaled) spTopPlate coordinate system.

var spTopPlate:Sprite = new Sprite();

board.addChild(spTopPlate);

 

// mcFront will be the first child on spTopPlate

spTopPlate.addChild(mcFront);

 

// Create frame for the 'magnifying glass' with drop shadow.

var glassFrame:Shape=new Shape();

glassFrame.graphics.lineStyle(2,0);

glassFrame.graphics.drawRect(-glassWidth/2,-glassHeight/2,glassWidth,glassHeight);

glassFrame.filters = [ new DropShadowFilter(2) ];

 

// Initially hidden

glassFrame.visible = false;

 

// glassFrame will be the second child on spTopPlate

spTopPlate.addChild(glassFrame);

 

// Create the 'magnifying glass' that will be used as a mask on mcFront (eventually).

var glass:Sprite=new Sprite();

glass.graphics.lineStyle(0,0);

glass.graphics.beginFill(200);

glass.graphics.drawRect(-glassWidth/2,-glassHeight/2,glassWidth,glassHeight);

glass.graphics.endFill();

 

//Initially hidden

glass.visible = false;

 

// glass will be the third (topmost) child on spTopPlate

spTopPlate.addChild(glass);

 

// Use a mask so we only see that part of mcFront behind the magnifying glass.

mcFront.mask = glass;

 

// Add event listeners

board.addEventListener(MouseEvent.MOUSE_DOWN, zoomIn);

stage.addEventListener(MouseEvent.MOUSE_MOVE, glassMove);

stage.addEventListener(MouseEvent.MOUSE_UP, zoomOut);

 

// Handler for MOUSE_DOWN event that performs zooming in.

function zoomIn(mev:MouseEvent):void {

 

//We want to use coordinates of the mouse but we want to keep

//the 'magnifying glass' cursor over the picture, so we find

//the point (goodX,goodY) that is the closest to the

//cursor but over which we cab still draw a valid magnifying glass.

 

var goodX:Number = Math.max(board.mouseX,glassWidth/(2*scaleFactor));

goodX = Math.min(goodX,boardWidth-glassWidth/(2*scaleFactor));

var goodY:Number= Math.max(board.mouseY,glassHeight/(2*scaleFactor));

goodY = Math.min(goodY,boardHeight-glassHeight/(2*scaleFactor));

 

//The point externalCenter is the clicked point on mcBack and

//internalCenter is the scaled up version of this point, which

//will be the same point on mcFront once it is scaled

//in the next two lines.

 

var externalCenter:Point=new Point(goodX,goodY);

var internalCenter:Point=new Point(goodX*scaleFactor,goodY*scaleFactor);

 

// Scale up mcFront to make internalCenter the correct point on mcFront

mcFront.scaleX = scaleFactor;

mcFront.scaleY = scaleFactor;

 

// Reposition mcFront so that the "same" point on mcFront and mcBack are aligned.

mcFront.x = externalCenter.x - internalCenter.x;

mcFront.y = externalCenter.y - internalCenter.y;

 

// Center the magnifying glass and its frame at the point (goodX,goodY).

glass.x = goodX;

glass.y = goodY;

glassFrame.x = glass.x;

glassFrame.y = glass.y;

 

// Make glass visible

glass.visible = true;

glassFrame.visible = true;

 

// Hide the (arrow) mouse cursor.

Mouse.hide();

 

//Activate the magnifying glass motion. See the glassMove function

//(the MOUSE_MOVE event handler) to see that the glassMove

//function returns immediately if the isMoving variable is false.

 

isMoving = true;

}

 

The handler for the MOUSE_MOVE event is effectively the same as zoomIn above, so we do not repeat the same comments here.

function glassMove(e:MouseEvent):void {

// This function does nothing if the isMoving flag has not yet been set to true.

if (!isMoving) return;

 

var goodX:Number = Math.max(board.mouseX,glassWidth/(2*scaleFactor));

goodX = Math.min(goodX,boardWidth-glassWidth/(2*scaleFactor));

 

var goodY:Number= Math.max(board.mouseY,glassHeight/(2*scaleFactor));

goodY = Math.min(goodY,boardHeight-glassHeight/(2*scaleFactor));

 

/* We align mcFront with mcBack so that we can easily track a corresponding point on both. After finding that point we will scale mcFront and realign (below). */

mcFront.x = mcBack.x;

mcFront.y = mcBack.y;

 

var externalCenter:Point=new Point(goodX,goodY);

var internalCenter:Point=new Point(goodX*scaleFactor,goodY*scaleFactor);

 

mcFront.scaleX = scaleFactor;

mcFront.scaleY = scaleFactor;

 

mcFront.x = externalCenter.x - internalCenter.x;

mcFront.y = externalCenter.y - internalCenter.y;

 

glass.x = goodX;

glass.y = goodY;

glassFrame.x = glass.x;

glassFrame.y = glass.y;

 

// The following method call makes smoother motion from a MOUSE_MOVE event.

e.updateAfterEvent();

}

The following is the the handler for MOUSE_UP event that performs zooming out.

function zoomOut(mev:MouseEvent):void {

// Rescale mcFront and reposition to align with mcBack

mcFront.scaleX = 1;

mcFront.scaleY = 1;

mcFront.x = mcBack.x;

mcFront.y = mcBack.y;

 

// Hide glass & glassFrame

glass.visible = false;

glassFrame.visible = false;

 

// Show the mouse cursor again

Mouse.show();

 

// Stop the motion of the "glass"

isMoving = false;

}

Back to AS3 How-Tos 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.