在AS3中单击MovieClip外部的事件

时间:2011-09-30 17:36:00

标签: actionscript-3 flash-cs5

有没有办法检测用户是否在MovieClip外点击?

例如,我需要检测它以关闭以前打开的菜单(如菜单栏样式:文件,版本,工具,帮助等)。

enter image description here

我怎样才能发现这种事件?谢谢!

5 个答案:

答案 0 :(得分:5)

向舞台添加一个监听器并检查stage是否是该事件的目标。

此处的代码示例: http://wonderfl.net/c/eFao

package
{
    import flash.display.Sprite;
    import flash.events.MouseEvent;

    public class FlashTest extends Sprite
    {

        private var _menu : Sprite;

        public function FlashTest()
        {
            _menu = new Sprite();
            _menu.x = 100;
            _menu.y = 100;
            _menu.alpha = 0.5;

            with(_menu.graphics)
            {
                beginFill(0xFF0000, 1);
                drawRect(0, 0, 300, 300);
                endFill();
            }

            addChild(_menu);

            _menu.addEventListener(MouseEvent.CLICK, onClickHandler);
            stage.addEventListener(MouseEvent.CLICK, onClickHandler);

        }

        private function onClickHandler(event : MouseEvent) : void
        {
            switch(event.target)
            {
                case _menu:
                    _menu.alpha = 0.5;
                    break;

                case stage:
                    _menu.alpha = 1;
                    break;
            }

        }

    }

}

答案 1 :(得分:3)

您可以为根元素的click事件添加侦听器:

MovieClip(root).addEventListener(MouseEvent.CLICK, clickObject);

然后在函数clickObject中,您可以检查您要点击的内容。

function clickObject(e:Event):void
{
    var hoverArray:Array = MovieClip(root).getObjectsUnderPoint(new Point(stage.mouseX, stage.mouseY));
    var hoverOverObject:* = hoverArray[hoverArray.length - 1];
}

hoverOverObject引用您单击的元素。通常这将是影片剪辑中的形状,因此您需要查看它的父级,然后将其与影片剪辑进行比较。如果点击不在下拉影片剪辑中,则触发关闭。

答案 2 :(得分:1)

var container:MovieClip = new MovieClip();
var mc:MovieClip = new MovieClip();
with(mc.graphics){
    beginFill(0xff0000,1);
    drawCircle(0,0,30);
    endFill();
}
mc.name = "my_mc";
container.addChild(mc);
addChild(container);
stage.addEventListener(MouseEvent.CLICK, action);
function action (e:MouseEvent):void 
{
    if(e.target.name != "my_mc"){
        if(container.numChildren != 0)
        {
            container.removeChild(container.getChildByName("my_mc"));
        }
    }
}

答案 3 :(得分:1)

使用捕获阶段:

button.addEventListener(MouseEvent.CLICK, button_mouseClickHandler);
button.stage.addEventListener(MouseEvent.CLICK, stage_mouseClickHandler, true);
//...

private function button_mouseClickHandler(event:MouseEvent):void
{
    trace("Button CLICK");
}
private function stage_mouseClickHandler(event:MouseEvent):void
{
    if (event.target == button)
        return;
    trace("Button CLICK_OUTSIDE");
}

请注意,使用stopPropagation()适用于一个对象,但有几个失败。这种方法对我有用。

答案 4 :(得分:0)

使用舞台和精灵(菜单)单击侦听器,首先执行sprite侦听器,然后将stopPropagation()方法应用于精灵的单击处理程序。像这样:

menu.addEventListener(MouseEvent.CLICK, handleMenuClick);
stage.addEventListener(MouseEvent.CLICK, handleStageClick);

private function handleMenuClick(e:MouseEvent):void{
    // stop the event from propagating up to the stage
    // so handleStageClick is never executed.
    e.stopPropagation();
    // note that stopPropagation() still allows the event
    // to propagate to all children so if there are children
    // within the menu overlay that need to respond to click
    // events that still works.  
}

private function handleStageClick(e:MouseEvent):void{
    // put hide or destroy code here
}

这个想法是鼠标点击任意位置会创建一个MouseEvent.CLICK事件,该事件从舞台起泡,向下穿过所有孩子到达目标,然后通过目标的父母备份到舞台。这里我们在目标是菜单覆盖时中断这个循环,不允许事件传播回父级,确保永远不会调用handleStageClick()方法。这种方法的好处在于它完全是通用的。舞台可以在叠加层下面有很多孩子,叠加层可以有自己的孩子,可以响应点击,一切正常。