在Actionscript 3中拖动时检测鼠标离开阶段

时间:2009-10-13 23:00:48

标签: flash actionscript-3 events mouseevent

Event.MOUSE_LEAVE在Actionscript 3中非常棒,但如果用户按住左侧(或右侧)鼠标按钮,它似乎不会触发。

有没有办法在鼠标按住时检测鼠标是否离开Flash影片?或者如果它是在flash电影之外发布的?

8 个答案:

答案 0 :(得分:27)

要获得所有这一切需要一点点黑客攻击。您必须存储鼠标是否在舞台之外,并相应地处理Event.MOUSE_LEAVE事件。这样做可以为您提供所有正常的鼠标功能,包括不会因为鼠标离开舞台而停止拖动。由于用户可能会回到舞台并继续拖动,因此等待用户在舞台上或舞台外释放鼠标。

var mouseOffStage:Boolean;

var bonk:YourDisplayObject = new YourDisplayObject()
addChild(bonk);
bonk.addEventListener(MouseEvent.MOUSE_DOWN, function():void {
  mouseOffStage = false;

  bonk.startDrag();

  stage.addEventListener(MouseEvent.MOUSE_UP, mouseUp);
  stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave);
  stage.addEventListener(MouseEvent.MOUSE_OUT, mouseOut);
  stage.addEventListener(MouseEvent.MOUSE_OVER, mouseOver);
})

private function mouseUp(e:MouseEvent) :void {
  trace("Mouse Up On Stage")
  bonk.stopDrag()
}

private function mouseLeave(e:Event) :void {
  if(mouseOffStage){
    trace("mouse up and off stage");
    bonk.stopDrag();
  }else{
    trace("mouse has left the stage");
    //no reason to stop drag here as the user hasn't released the mouse yet
  }
}

private function mouseOut(e:MouseEvent) :void {
  mouseOffStage = true;
  trace("mouse has left the stage")
}

private function mouseOver(e:MouseEvent) :void {
  mouseOffStage = false;
  trace("mouse has come back on stage");
}

黑客是当鼠标从舞台上释放时MOUSE_LEAVE事件而不是MOUSE_UP事件被触发,所以你必须跟踪鼠标是否已经离开舞台了它被释放了。

拖动完成后,您当然希望删除与检测鼠标输出和鼠标悬停相关的所有事件监听器,但该代码被遗漏以便于阅读。

答案 1 :(得分:4)

这就是我的所作所为:

mc.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

private function onMouseDown(_e:MouseEvent):void
{
    mc2.startDrag(params);

    stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
    stage.addEventListener(Event.MOUSE_LEAVE, onMouseLeave);
    stage.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);
}

private function onMouseUp(_e:MouseEvent):void
{
    ms2.stopDrag();
}

private function onMouseLeave(_e:Event):void
{
    mc2.stopDrag();
}

private function onMouseOut(_e:MouseEvent):void
{
    if (e.stageX <= 0 || e.stageX >= stage.stageWidth || e.stageY <= 0 || e.stageY >= stage.stageHeight)
    {
        mc2.stopDrag();
    }
}

答案 2 :(得分:2)

这里有几个棘手的陷阱:

奇怪的是,在Chrome + Firefox中,不会为OPAQUE TRANSPARENTWINDOW调度MOUSE_LEAVE事件。它只是不会发射 - 鼠标向下或向上。

使用Event它可以正常工作。那个花了我很长时间才发现! grr ... WMODE


其次,请确保您使用Event.MOUSE_LEAVE作为MouseEvent处理程序的参数类型,而不是MOUSE_LEAVE。如果您尝试使用e:MouseEvent处理endDrag,您将收到一个您可能永远看不到的错误(除非您使用的是调试Flash播放器)。这是一个非常容易犯的错误,因为你可能将所有其他处理程序指向同一个方法。

以下是我的工作:(只需从mouseLeave(e:Event)

打电话给我的主stage.addEventListener(MouseEvent.MOUSE_MOVE, drag); stage.addEventListener(MouseEvent.MOUSE_UP, endDrag); stage.addEventListener(Event.DEACTIVATE, endDrag); stage.addEventListener(Event.MOUSE_LEAVE, mouseLeave); private function mouseLeave(e:Event):void { endDrag(new MouseEvent("MOUSE_LEAVE")); } public function endDrag(evt:MouseEvent):void { /// handle end drag }
{{1}}

答案 3 :(得分:1)

我在PDF类型查看器中遇到了类似的问题,我必须构建到Flex应用程序中。我希望即使鼠标离开舞台或浏览器窗口,平移功能仍然有效。以下是我完成此操作的方法,我已更改代码以删除对Flex Framework类的引用,因此这应适用于任何AS3项目。在mouseDown我会开始在计时器上跟踪这些值。 _client可以是目标阶段中的任何flash.display.DisplayObject。在我的情况下,它是一个Flex mx.controls.SWFLoader对象,但在你的情况下,我认为它将是拖动目标:

private function get currentMouseX():Number
{
     return _client.stage.mouseX; 
}

private function get currentMouseY():Number
{
     return _client.stage.mouseY; 
}

stage.mouseXstage.mouseY值是相对于舞台定义的,无论鼠标是在舞台上还是在浏览器窗口中(至少在Flash Player 10中,我没有在早期的Flash播放器版本)。要查看鼠标是否在舞台之外,只需测试并查看这些值是否在舞台内,如下所示:

if (currentMouseY < 0 || 
    currentMouseY > _client.stage.height || 
    currentMouseX < 0 || 
    currentMouseX > _client.stage.width)
{
     // Do something here
}

编辑:对于在舞台之外检测mouseUp事件,如果在舞台上注册一个侦听器,即使事件发生在舞台或浏览器之外,也会发出mouseUp。这是我如何处理事件函数以供参考的代码。 _client对象可以是任何flash.display.DisplayObject

 // attach the events like so when you initialize
 _client.addEventListener(MouseEvent.MOUSE_DOWN  , handleMouse);   
 _client.addEventListener(MouseEvent.MOUSE_OUT   , handleMouse);
 _client.addEventListener(MouseEvent.MOUSE_OVER  , handleMouse);
//

// and handle them like this:
 private function handleMouse(e:MouseEvent):void
 {
      switch(e.type)
      {

          case "mouseDown":

         // add listeners, notice the mouse move and mouse up are 
         // attached to the stage, not the display object this way
         // events are issued regardless of whether the mouse is in 
         // the stage or even within the browser window

         _client.stage.addEventListener(MouseEvent.MOUSE_UP, handleMouse);
         _client.addEventListener(MouseEvent.CLICK, handleMouse);      
         _client.stage.addEventListener(MouseEvent.MOUSE_MOVE, handleMouse);    


         // remove listeners     
         _client.removeEventListener(MouseEvent.MOUSE_DOWN, handleMouse); 

         //
         // commands / actions 

         break;


         case "mouseUp":

         // add listeners
        _client.addEventListener(MouseEvent.MOUSE_DOWN, handleMouse); 


         // remove listeners 
         _client.stage.removeEventListener(MouseEvent.MOUSE_UP, handleMouse);
         _client.stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouse);    


         // commands/actions 

         break;


         case "click":


         // add listeners
         _client.addEventListener(MouseEvent.DOUBLE_CLICK, handleMouse);


         // remove listeners    
         _client.removeEventListener(MouseEvent.CLICK, handleMouse); 


         // commands / actions

         break;

         case "mouseMove":

         // add listeners


         // remove listeners
         _client.stage.removeEventListener(MouseEvent.MOUSE_MOVE, handleMouse);
         _client.removeEventListener(MouseEvent.CLICK, handleMouse);   


         // commands 

         break;

         case "mouseOut":

         // add listeners


         // remove listeners

         // commands / actions

         break;

         case "mouseOver":

         // add listeners


         // remove listeners


         // commands /actions

         break;
     }
 }

编辑:删除了对Flex框架类的引用 编辑:我记得当在Mac OSX上的Safari浏览器中运行应用程序时,浏览器窗口之外的事件可能存在一些问题。如果您使用它,请确保在该浏览器中测试此代码。这在我的申请中不是问题,所以我没有进一步研究这个问题。

答案 4 :(得分:0)

如果您正在拖动MovieClip,这似乎很有效。

stage.addEventListener(MouseEvent.MOUSE_OUT, onMouseOut);

编辑 - 没关系

答案 5 :(得分:0)

  

有没有办法在鼠标按住时检测鼠标是否离开Flash影片?

不是我知道的

  

或者如果它是在flash电影之外发布的?

当你在外面释放时,会发生事件.MOUSE_LEAVE。

这里有更多信息 http://blog.zupko.info/?p=3 见JIMISAACS评论。

答案 6 :(得分:0)

    var youMax_X:Number; //set this var to Max x
    var youMax_Y:Number; //set this var to `enter code here`Max y

    var dragBounds:Rectangle = new Rectangle(0,0,youMax_X,yourMax_Y);

    stage.addEventListener(MouseEvent.MOUSE_DOWN,handleDown);
    stage.addEventListener(MouseEvent.MOUSE_UP,handleUp);


    private function handleDown(e:Event):void{
            this.startDrag(false,dragBounds);
    }
    private function handleUp(e:Event):void{
        this.stopDrag();
    }

答案 7 :(得分:0)

这是正确的答案。您将DisplayObject传递给自定义类,并将其拖动到鼠标向上或鼠标离开阶段。随意定制:

package fanlib.gfx
{
    import flash.display.DisplayObject;
    import flash.display.Stage;
    import flash.events.Event;
    import flash.events.MouseEvent;
    import flash.geom.Point;
    import flash.ui.Mouse;

    public class Drag
    {
        private var obj:DisplayObject;
        private var point:Point = new Point();
        private var stg:Stage;

        public function Drag(obj:DisplayObject)
        {
            this.obj = obj;
            stg = Stg.Get();
            stg.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
            stg.addEventListener(MouseEvent.MOUSE_UP, stopDrag);
            //stg.addEventListener(Event.MOUSE_LEAVE, stopDrag); // sh*t just won't fire
            point.setTo(stg.mouseX, stg.mouseY);
        }

        private function mouseMove(e:MouseEvent):void {
            if (stg.mouseX <= 0 ||
                stg.mouseY <= 0 ||
                stg.mouseX >= stg.stageWidth ||
                stg.mouseY >= stg.stageHeight) {
                stopDrag();
                return;
            }
            obj.x += stg.mouseX - point.x;
            obj.y += stg.mouseY - point.y;
            point.setTo(stg.mouseX, stg.mouseY);
        }

        public function stopDrag(e:* = null):void {
            stg.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
            stg.removeEventListener(MouseEvent.MOUSE_UP, stopDrag);
            //stg.removeEventListener(Event.MOUSE_LEAVE, stopDrag);
        }
    }

}