Creating a custom mouse pointer in AS3 seems like a basic task, and it is, kind of. There are some pitfalls that developers seem to fall into more often than one would think. In this post I’m going to walk through the whole process of making a custom cursor.

This is the end result:

The Flash plugin is required to view this object.

Tools used in this post

  • Flash CS3
  • Illustrator
  • Eclipse

These tools are all optional and not needed to follow the post

The pointer

First we need graphics for the pointer. If you import graphics from Illustrator there are a couple of things that are good to know.

  • Changing all the lines to fills will prevent the image to look funky when resizing it. (Object, Path, Outline Stroke in Illustrator)
  • If you’ve got text in the graphics you’ll want to outline that. Right click (ctrl click on the mac) and choose “Create Outlines”.
  • If you import the graphics instead of just dragging it in to flash you’ll get a “incompatibility report” if something is wrong with the illustration.(File, Import, Import to Library…).

When we have our graphics, link it to a class! While we’re at it, let’s create a document class for the main time line as well. Now we don’t have to use the flash code editor at all and can use our favourite IDE instead (Eclipse in my case).

Let’s code

In our document class we first have to instantiate the cursor class and add it to the scene.
// in a good IDE, these two lines add themselves
import flash.display.Sprite;
import src.Cursor;
// our document class pedagogically named "DocumentClass" :P
public class DocumentClass extends Sprite
{
// Declarations go here
public var cursor:Cursor;
// And Constructor here
public function DocumentClass():void
{
// instantiate the cursor
// and add it to the scene
cursor = new Cursor();
addChild(cursor);
}
}

This is how it looks if we run the application now.
<p>Custom cursor flash. First compile</p>

As seen above the cursor graphics is visible at top left even though we do not need it. Right now it is just littering the scene. Let’s make it go away.
cursor.visible = false;
And let’s hide the mouse cursor as well.
// We need this import
import flash.ui.Mouse;
// then hide it like this.
Mouse.hide();

As soon as the mouse enter the scene we want the cursor to be visible again. And when it leaves we have to make invisible. Otherwise it will just lie and clutter the scene at its last registration point. So, two new events:
// needed imports
import flash.events.Event;
import flash.events.MouseEvent;
// The events
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
// The first function
private function mouseMove(e:MouseEvent):void
{
// Since there is no MOUSE_ENTER event
// we'll have to make the cursor visible here,
// hence the if statement.
if (!cursor.visible) cursor.visible = true;
// And pin it to the mouse position.
cursor.x = e.stageX;
cursor.y = e.stageY;
}
// second function
private function mouseLeave(e:Event):void
{
// The anti littering function
// Besides making our cursor invisible
// we may also want to remove eventlisteners
// and stuff we don't need to free up resourcers
// for the user, just remember to turn them on
// again in the mouseMove function.
cursor.visible = false;
}

We’re almost done.
<p>Custom cursor. second compile.</p>

Final touches

As new stuff gets added to the scene we don’t want our nice cursor to get concealed by it. To prevent that from happening we can add these lines.
// check if there are more objects on the scene
if(numChildren > 1)
{
// set the cursor index so the cursor has the
// highest index the other objects on the
// scene will get new indexes automatically
setChildIndex(cursor, (numChildren - 1));
}

depending on the project we need the cursor in, we may need to turn these lines into a little function and call it from more places in the code. Ie, the click event, the enter frame event or whenever a new object gets added, because right now the index will only be updated when you move the cursor.
<p>Custom cursor. second compile.</p>

If we move the cursor around the scene now we’ll notice some stuttering. To get rid of this we need to call the updateAfterEvent(). This will make flash rerender as soon as the event completes. So, at the bottom of our mouseMove function we add this line.
e.updateAfterEvent.updateAfterEvent();
This is the final result.

The Flash plugin is required to view this object.

Conclusion

There really is no perfect way to do this. If you have an application that is heavy on the cpu, the cursor can get laggy even though you did everything by the book. Maybe one day Adobe will improve the mouse ui but until then, make sure to remove the cursor on mouse out, use the updateAfterEvent() and set the right index of the cursor when needed.

If you want you can download this little project.

/ Johan