代码之家  ›  专栏  ›  技术社区  ›  nicks

如何检查鼠标是否在电影剪辑上?

  •  1
  • nicks  · 技术社区  · 12 年前

    没有听众参与。 问题是,我可以使用 鼠标悬停(_O) 鼠标输出(_O) 侦听器,但如果您在MovieClip上快速拖动鼠标,其中一个侦听器可能无法激活。我试过好几次了。

    4 回复  |  直到 12 年前
        1
  •  11
  •   L0LN1NJ4    12 年前

    我从来没有遇到过mouseOver和mouseOut的问题。

    但您可以使用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);
    }
    

    如果您确信该属性是可用的并且是从您调用的位置设置的,那么您也可以使用stage.mouseX和stage.mouse Y(而不是localToGlobal)。

    我还没有测试代码,但我认为它应该可以工作。

    (编辑)

    但是,如果你想绝对确定鼠标经过了一个对象——即使你走得太快以至于完全跳过了它,你也必须检查两帧鼠标点之间的点。

    例如:

    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
    }
    

    您可以记住最后一个状态是否已结束,并在isOver!=时调度自定义事件结束了。如果你在while循环中这样做,你会得到高度准确的鼠标过度检测。

    但我敢打赌,shapeFlag=true的hitTestPoint相当占用CPU,尤其是在一帧中大量使用的情况下。因此,在这种情况下,您可能希望将此MAX_DIST设置为尽可能高的值。

        2
  •  2
  •   Zhafur    12 年前

    那就用数学吧。

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

    请注意,这取决于movieclips注册点。。。在这种情况下,reg点位于movieclip的中间。

    另一种方式是 hitTestObject() 内置函数,具有 shapeFlag = true;

        3
  •  1
  •   oxygen    12 年前

    如果鼠标“足够快”通过,那么操作系统可能一开始就没有向Flash发送任何鼠标事件。移动鼠标的速度远远超过其分辨率(或操作系统可以处理的速度)将产生您所看到的效果(事实是,屏幕的那部分没有处理鼠标事件),否则mouse_OVER肯定会触发(如果鼠标确实在电影剪辑上生成了至少一个移动事件)。

    然而MOUSE_OUT事件, 可以 由于各种操作系统或浏览器的安全限制,如果鼠标离开舞台区域(离开Flash),则不会启动。

    要解决此问题,请为注册侦听器 stage::flash.events.Event.DEACTIVATE stage::flash.events.Event.MOUSE_LEAVE ,在每个Sprite/MovieClip中,您也在监听MOUSE_OUT,重用相同的处理程序函数。

    mouseLeave事件(由stage触发)是专门为您的问题创建的:“当指针移出stage区域时,由stage对象调度。如果按下鼠标按钮,则不会调度事件。”如果它触发,则您应该像mouse_out一样处理处于mouse_OVER“状态”的任何movieclip(假设您有这样的状态)。如果鼠标按钮在离开舞台区域时被按下,用户可能会在某个时候释放它,而DEACTIVATE将在舞台上触发。

        4
  •  1
  •   turbosqel    12 年前

    您还可以监听舞台鼠标移动,并检查鼠标下的剪辑:

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

    并检查您的电影剪辑是否在阵列内。