nix
nix

Reputation: 2285

How to check if mouse is over a MovieClip?

No listeners involved. The thing is, I can use MOUSE_OVER and MOUSE_OUT listeners, but if you drag a mouse over a MovieClip quickly enough, one of these listeners may not be activated. I've tried it several times.

Upvotes: 1

Views: 11231

Answers (4)

oxygen
oxygen

Reputation: 6029

If the mouse passed by "quickly enough" then maybe the OS didn't send any mouse events to Flash for that portion of the screen, in the first place. Moving the mouse a lot faster than its resolution can fire (or the OS can handle) will have the effect you are witnessing (and the truth is, no mouse events were handled for that portion of the screen), otherwise MOUSE_OVER will surely fire (if the mouse does indeed generate at least one move event over a movie clip).

The MOUSE_OUT event, however, might not fire if the mouse leaves the stage area (leaves Flash), because of various OS or browser security limitations.

To fix this, register listeners for stage::flash.events.Event.DEACTIVATE and stage::flash.events.Event.MOUSE_LEAVE, inside every Sprite/MovieClip you are also listening for MOUSE_OUT, reusing the same handler function.

The mouseLeave event (fired by stage) is especially created for your problem: "Dispatched by the Stage object when the pointer moves out of the stage area. If the mouse button is pressed, the event is not dispatched." If it fires, the you should handle it like MOUSE_OUT for any movieclip in a MOUSE_OVER "state" (supposedly you have such a state). If the mouse button was pressed when it left the stage area, the user will likely release it at some point and DEACTIVATE will fire on stage instead.

Upvotes: 1

turbosqel
turbosqel

Reputation: 1542

You can also listen for stage mouse move and check what clips are under mouse :

stage.addEventListener(MouseEvent.MOUSE_MOVE , onMouseMove);
function onMouseMove(e:MouseEvent):void {
    trace(stage.getObjectsUnderPoint(new Point(e.stageX , e.stageY)));
}

and check if Your MovieClip is inside array .

Upvotes: 1

L0LN1NJ4
L0LN1NJ4

Reputation: 424

I have never had a problem with mouseOver and mouseOut.

But you can use hitTestPoint:

function detectMouseOver(d:DisplayObject):Boolean
{
    var mousePoint:Point = d.localToGlobal(new Point(d.mouseX,d.mouseY));
    return d.hitTestPoint(mousePoint.x,mousePoint.y,true);
}

You could also use stage.mouseX and stage.mouseY (and not localToGlobal), if you're certain that that property is available and set from where you're calling.

I haven't tested the code but I think it should work.

(edit)

But if you want to be absolutely sure that the mouse went over an object - even if you go so fast as to completely skip over it, you would have to check for points between mouse points of two frames.

That would make it, for instance:

d.addEventListener(Event.ENTER_FRAME, checkMouseOver);

var lastPoint:Point;
const MAX_DIST:Number = 10;

function checkMouseOver(e:Event):void
{
    var isOver:Boolean = false;

    var d:DisplayObject = e.currentTarget as DisplayObject;
    var thisPoint:Point = d.localToGlobal(new Point(d.mouseX,d.mouseY))

    if (lastPoint)
    while (Point.distance(thisPoint,lastPoint) > MAX_DIST)
    {
        var diff:Point = thisPoint.subtract(lastPoint);
        diff.normalize(MAX_DIST);
        lastPoint = lastPoint.add(diff);

        if (d.hitTestPoint(lastPoint.x,lastPoint.y,true))
        {
            isOver = true;
            break;
        }
    }
    if (d.hitTestPoint(thisPoint.x,thisPoint.y,true))
    isOver = true;

    lastPoint = thisPoint;

    //do whatever you want with isOver here
}

You could remember if last state was over and dispatch a custom event when isOver != wasOver. If you do that inside the while loop you get a highly accurate mouse over detection.

But I bet that hitTestPoint with shapeFlag = true is fairly CPU heavy, especially if used a lot in one frame. So in this case you may want to set this MAX_DIST as high as you can.

Upvotes: 11

Zhafur
Zhafur

Reputation: 1624

Use math then.

if(mouseX>mc.x-(mc.width/2) && mouseX<mc.x+(mc.width/2) && mouseY>mc.y-(mc.height/2) && mouseY<mc.y+(mc.height/2)){
     hovered = true;
     //do stuff..
}else{
     if(hovered){
           hovered=false;
           //do rollout stuff..
     }
}

Note that it depends on the movieclips reg point... in this case, the reg point is in the middle of the movieclip.

An another way is hitTestObject() built in function with shapeFlag = true;.

Upvotes: 2

Related Questions