The cursor has left the Stage, or has it?

January 28th, 2008 . by polyGeek

A 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?

Share and Enjoy: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • del.icio.us
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati
  • Digg
  • Facebook

5 Responses to “The cursor has left the Stage, or has it?”

  1. comment number 1 by: Jon B

    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)

  2. comment number 2 by: Andrew Traviss

    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;
    }

  3. comment number 3 by: polyGeek

    @Andrew, that’s a nice solution. It’s a lot of code for such a seemingly simple thing isn’t it?

  4. comment number 4 by: polyGeek

    @Jon, “the problem with JS”? Please, there’s a lot more than just one. :-)

    Seriously, JS is great. But browser DOMs frakking suck!

  5. comment number 5 by: Alejandro HR

    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

Name

Mail (never published)

Website

- Why ask? This confirms you are a human user!

   




© Copyright 2008 polyGeek.com / Dan Florio, All Rights Reserved Except Where Explicitly Stated
Web Developement Blogs - Blog Catalog Blog Directory
M2 Websites