The cursor has left the Stage, or has it?
January 28th, 2008 . by polyGeekA reader asked me if there is a reliable way to determine if the mouse cursor has left the Stage in Actionscript 2. I believe the best approach is to use Javascript to see which object in the DOM has the mouse over it. But it would be nice if there were a reliable way to do it in Actionscript.
Here’s what I came up with which amounts to zero:
- There are no Stage events to listen to so that doesn’t help.
- Checking the _xmouse, _ymouse on an interval doesn’t really help because the last position of the mouse cursor is reported when the cursor leaves the Stage.
- Creating a large MovieClip to cover the Stage and listening for onRollOut on it won’t help because any MovieClips above it will trigger the onRollOut when you rollOver another MovieClip.
It’s rather simple to do with Actionscript 3 but that isn’t an option for my friend.
[ download code ]
package {
import flash.display.Sprite;
import flash.events.Event;
public class MouseOverStage extends Sprite {
public function MouseOverStage() {
stage.addEventListener( Event.MOUSE_LEAVE, mouseOutHandler );
}
private function mouseOutHandler( event:Event ):void {
trace( "mouse has left the stage" );
}
}
}
Anyone have a suggestion?












The problem with using JS is it only triggers if you leave the flash and rollover an HTML Element - which is not always the case (rolling over browser chrome cannot be detected with JS)
I’ve run into this issue in the past, and the only way I’ve come up with is not suitable for most projects. I will share it anyway, though.
Basically you decide on a gutter width to have around the Flash content. This gutter will actually be part of the Flash movie. I will choose a gutter of 60 pixels for this example. Any number works, but smaller numbers cause issues - explained below.
The approach is twofold. First, if the cursor is within the gutter region, you treat it as if it is rolled out. Secondly, you keep track of the cursor’s acceleration, and if it ever changes by 60 pixels or more, you watch to see if it remains completely still. If so, you roll it out. This covers the case where the user rolled the mouse out so fast that it skipped over the buffer region. It’s not perfect, but as long as the gutter is large enough, it works.
To see it in action, just attach the code below to a movie clip on the stage.
onClipEvent(load)
{
var lastVelocity:Number = 0;
var threshold:Number = 60;
var onNotice:Boolean = false;
var maxWidth:Number = 550;
var maxHeight:Number = 400;
}
onClipEvent(enterFrame)
{
// Calculate velocity based on current position vs the position of the mouse
var newVelocity:Number = Math.sqrt(((_parent._xmouse-_x)*(_parent._xmouse-_x))+((_parent._ymouse-_y)*(_parent._ymouse-_y)));
// Update my position
_x = _parent._xmouse;
_y = _parent._ymouse;
// Check whether I am in the gutter
if(_x>maxWidth-threshold)
{
_visible = false;
}
else if(_xmaxHeight-threshold)
{
_visible = false;
}
else if(_ythreshold)
{
// I’ve decelerated too fast - watch to see if I’m still moving next frame
onNotice = true;
}
else
{
// If I’m moving at all, I must be in the frame
onNotice = false;
_visible = true;
}
}
}
lastVelocity = newVelocity;
}
@Andrew, that’s a nice solution. It’s a lot of code for such a seemingly simple thing isn’t it?
@Jon, “the problem with JS”? Please, there’s a lot more than just one. :-)
Seriously, JS is great. But browser DOMs frakking suck!
I had the same issue when I was doing an interactive MPU, in flash 6 :[… the best solution I found was the simplest, a movieclip called mouseController, on top of the app, with two events:
mouseControler.onRollOver
mouseControler.onRollOut
I can’t remember if I was leaving 1 pixel in the border of that movieclip, I think I did… anyway. It’s the most efficient way.
The only problem that it has is that the rest of the application has to be coded with coordinates to detect the rollover of the different elements, and with useHandCursor on and off all the time ;).
Hope it helps.
Leave a Reply