In this example we combine programmatic masking with dragging techniques to create a flashlight effect. We make important observations about visibility and the stacking order of display objects versus their response to mouse events.
Download
- Flash CS3 file as3_masking_3.fla
Download the well-commented fla file for the swf displayed above.
To create the effect we imported to the Stage two versions of the same photo - a dark one and a normal one -- and converted them to MovieClips. We placed the dark version beneath the normal version and masked the normal version by a programmatically created Sprite. We drew a disk in the masking Sprite which serves as a spotlight. Then we drag the masking Sprite. It is rather staightforward if you simply want the mask to follow the mouse without the user pressing the mouse button. If you want the spotlight to be dragged only after MOUSE_DOWN event, you run into a subtle problem: objects that are invisible or are hidden behind other display objects do not respond to mouse events. A mask is invisible; the visibility of regions in the light photo changes according to the position of the mask and the dark photo is behind it. The code below with detailed comments shows how to handle the problem.
/*
We imported to the Stage two versions of a jpeg photo
from our recent PREP workshop at URI. We turned them
into MovieClips, lightClip and darkClip. We positioned
the clips on the Stage, light version over the dark version,
and gave them instance names mcLightPic and mcDarkPic.
Now we create a new Sprite, lightSpot. Then we draw a circle
in lightSpot. Since lightSpot is a child of mcDarkPic,
its position (which is the position of its center)
is relative to mcDarkPic or mcLightPic). We position
lightSpot in the center of our photos.
*/
var lightSpot:Sprite = new Sprite();
mcDarkPic.addChild(lightSpot);
lightSpot.graphics.lineStyle(1,0x000000);
lightSpot.graphics.beginFill(0x0000FF);
lightSpot.graphics.drawCircle(0,0,50);
lightSpot.graphics.endFill();
lightSpot.x = 175;
lightSpot.y = 132;
/*
We are assigning lightSpot as a mask for mcLightPic.
Hence, the only visible portion of mcLightPic is going
to be the portion visible through lightSpot. Outside
of lightSpot, we will see the background
which is the dark image.
*/
mcLightPic.mask=lightSpot;
/*
We want the light spot to respond to the MOUSE_DOWN event.
A mask will not respond to a mouse event as invisible
objects do not respond to mouse events and the mask is invisible.
The invisible portions of mcLightPic will not respond to MOUSE_DOWN
either but the visible portions will. Thus, if we assign to mcLightPic
an event listener that listens to MOUSE_DOWN, the only part of mcLightPic
that will respond is the visible part of mcLightPic;
that is, the part under the light spot. This is the effect that we want.
The MOUSE_DOWN listener assigns to the Stage a listener that listens to
MOUSE_MOVE and allows dragging lightSpot but only within the photos area.
The latter part is accomplished via boundedX and boundedY functions
defined below. (See our Tour of Drag and Drop Techniques
tutorial for an analysis of dragging techniques.)
*/
mcLightPic.addEventListener(MouseEvent.MOUSE_DOWN, startMove);
function startMove(evt:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_MOVE, pointMove);
}
function pointMove(e:MouseEvent):void {
lightSpot.x = boundedX(mcLightPic.mouseX);
lightSpot.y = boundedY(mcLightPic.mouseY);
e.updateAfterEvent();
}
stage.addEventListener(MouseEvent.MOUSE_UP, stopMove);
function stopMove(e:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_MOVE, pointMove);
}
function boundedX(inX:Number):Number {
if (inX < 0) {
return 0;
}
if (inX > 350) {
return 350;
}
return inX;
}
function boundedY(inY:Number):Number {
if (inY < 0) {
return 0;
}
if (inY > 263) {
return 263;
}
return inY;
}
On the next page, we show an interesting effect created by animating a mask with EnterFrame event.











