A Custom Mouse Pointer

Since creating a custom mouse pointer is of interest in itself, we created a very simple appplet displayed below which illustrates only that aspect. We extracted the portions of the code from the main example of this tutorial that deal with the issue of a custom pointer.

Download

Download the fla file for the swf displayed above.

Here is the simple code behind the applet.

As before, we are creating a Sprite, spBoard. We add spBoard as a child of 'this', that is, the MainTimeline, and position spBoard within the main movie. Then, we call a function (defined later in the script) that draws a white square in spBoard.

var spBoard:Sprite=new Sprite();

this.addChild(spBoard);

spBoard.x=70;

spBoard.y=75;

drawBoard();

When the user mouses over spBoard, the mouse pointer will be replaced by our custom pointer -- in our case a disk with a gradient fill. In order to avoid drawing a gradient fill at runtime (a bit of a pain), we drew our disk by hand and converted it to a MovieClip, eraserClip. We deleted the clip from the Stage; the clip remained in the Library. From the menu in the upper right corner of the Library window, we chose 'Linkage' and checked 'Export to ActionScript'. If you do not associate a class with your clip, Flash will ask you if you want a class for your clip created automatically, click OK. (Flash creates a subclass of the MovieClip class named eraserClip which contains a constructor.) The linkage is established. After the linkage is established (and only after that), we can create instances of our clip at runtime. We do it below. For simplicity, we keep the names mcEraser and eraserClip, although nothing here is being erased.

var mcEraser:eraserClip= new eraserClip();

Without the line below, the code wouldn't work. Why? The portion of spBoard hidden under the custom pointer (which is a MovieClip and thus an InteractiveObject) would not receive mouse events; mcEraser would receive them. Try commenting the line out, and decyphering the havoc that happens. The havoc does follow logically from the way event listeners below are assigned.

mcEraser.mouseEnabled=false;

The square is drawn as before:

function drawBoard():void {

spBoard.graphics.lineStyle(1,0x000000);

spBoard.graphics.beginFill(0xFFFFFF);

spBoard.graphics.drawRect(0,0,250,250);

spBoard.graphics.endFill();

spBoard.filters = [ new DropShadowFilter() ];

}

We attach the appropriate listeners to spBoard. The listeners will cause the mouse pointer to change when the user mouses over spBoard (ROLL_OVER). When the user moves the mouse outside spBoard (ROLL_OUT), the pointer returns to the regular shape. When the user moves the mouse over spBoard (MOUSE_MOVE), the custom pointer follows. The code responsible for that is placed in event handlers 'boardOut', boardOver', and boardMove.

spBoard.addEventListener(MouseEvent.ROLL_OUT,boardOut);

spBoard.addEventListener(MouseEvent.ROLL_OVER,boardOver);

spBoard.addEventListener(MouseEvent.MOUSE_MOVE,boardMove);

When the user moves the mouse over spBoard, our custom pointer, mcEraser, is added as a child of the MainTimeline so it can now be visible. The regular mouse pointer is hidden and mcEraser is placed at the mouse position. In boardMove handler, mcEraser will be made to follow the mouse.

function boardOver(e:MouseEvent):void {

this.addChild(mcEraser);

mcEraser.x=stage.mouseX;

mcEraser.y=stage.mouseY;

Mouse.hide();

}

When the mouse moves away from spBoard, and the MainTimline contains mcEraser as a child (this.contains(mcEraser)), the child is removed and the regular mouse pointer shows. The test, this.contains(mcEraser), in this example is an overkill. In general, though, an attempt to remove nonexisting children causes an error.

function boardOut(e:MouseEvent):void {

if(this.contains(mcEraser)){

this.removeChild(mcEraser);

Mouse.show();

}

}

The next function is executed when the user moves the mouse while over spBoard. The mcEraser coordinates are set to those of the mouse, so mcEraser follows the mouse. e.updateAfterEvent() (which can be used with MOUSE_MOVE) causes the motion to appear smoother. Without e.updateAfterEvent(), the position would not be updated until the next frame. At 12 fps, it causes a bit of a jitter.

function boardMove(e:MouseEvent):void {

mcEraser.x=stage.mouseX;

mcEraser.y=stage.mouseY;

e.updateAfterEvent();

}

 

Back to Basic Tutorials              Back to Flash and Math Home

The site www.flashandmath.com is maintained by Doug Ensley (doug@flashandmath.com) and Barbara Kaskosz (barbara@flashandmath.com).
It has been developed with partial funding from the National Science Foundation and the Mathematical Association of America.