使用AS3在Flash中执行鼠标翻转/转出检测的首选方法是什么

时间:2011-10-03 23:16:00

标签: actionscript-3 mouse rollover hittest rollout

假设我们有一个有两个正方形的舞台,如下所示: Our example Flash stage

假设我们想要最初隐藏的黄色方块,只要鼠标光标位于红色方块的边界内,我们就会喜欢它 - 黄色方块将是可见的,并且只要鼠标光标超出了红色方块的范围 - 黄色方块将被隐藏。

直观的方法是写下这样的东西:

inSqr.visible = false;
outSqr.addEventListener (MouseEvent.ROLL_OVER,sqrOver);
outSqr.addEventListener (MouseEvent.ROLL_OUT,sqrOut);

function sqrOver(e:MouseEvent) {
    inSqr.visible = true;
}

function sqrOut (e:MouseEvent) {
    inSqr.visible = false;
}

但是,使用此代码 - 只要将鼠标光标移动到黄色方块内 - 它显然是 RED 方块的 ROLL_OUT - 因此sqrOut函数被触发 - 使黄色方块消失,一旦黄色方块不存在 - 光标突然再次位于 RED 方格的范围内 - 所以sqrOver函数 被调用 - 带回黄色方块的可见性 - 触发sqrOut等等,从而当鼠标诅咒在他身上时创建一个“闪烁”的黄色方块: 黄色方块消失,一遍又一遍地重复出现。

对此可能的“修复”是在光标位于黄色内部时移除红色的转出事件的侦听器(如果它在黄色内部,它肯定也在红色内部),并在将其带回时通过在上面的代码中添加它,它就出来了:

 inSqr.addEventListener (MouseEvent.ROLL_OVER,insqrOver);
 inSqr.addEventListener (MouseEvent.ROLL_OUT,insqrOut);
 function insqrOver(e:MouseEvent) {
     if (outSqr.hasEventListener (MouseEvent.ROLL_OUT)) {
         outSqr.removeEventListener(MouseEvent.ROLL_OUT,sqrOut);
     }
     inSqr.visible = true;
 }
 function insqrOut(e:MouseEvent) {
     if (!outSqr.hasEventListener (MouseEvent.ROLL_OUT)) {
         outSqr.addEventListener(MouseEvent.ROLL_OUT,sqrOut);
     }
 }

这很有效。 但它很麻烦。您必须为红色方块内的每个任何对象执行此操作 - 导致长代码和许多事件侦听器以及连续侦听器注册和取消注册。


几年前,有人向我建议了这种技术:

 outSqr.addEventListener (Event.ENTER_FRAME,hoverCheck);

 function hoverCheck (e:Event) {
     if (e.currentTarget.hitTestPoint(stage.mouseX,stage.mouseY,true)) {
         inSqr.visible = true;
     }
     else {
         inSqr.visible = false;
     }
 }

这是一个简单的短代码。 但是,如果您的项目确实不需要使用ENTER_FRAME事件,则会产生不必要的开销和重复运行命中测试的cpu周期。 此外,如果红色正方形覆盖整个舞台(与舞台尺寸相同) - 它会产生问题(它不起作用)。


有没有人意识到一种简单优雅的方法来实现这一目标 - 一个不会涉及过于繁琐和冗长的代码,并且不必使用重复计时器一次又一次地进行测试......?

3 个答案:

答案 0 :(得分:2)

将黄色方块放在红色方块内。

outSqr.addChild(inSqr);

这将很好地解决您的问题。请确保outSqr是SpriteMovieClip类的实例。

答案 1 :(得分:1)

我不知道这对你的情况有帮助,但是你也可以禁用inSqr的鼠标动作,然后你可以将鼠标悬停在不触发ROLL_OUT的黄色方块上

inSqr.mouseEnabled = false

..然后你可以使用它:

inSqr.visible = false;
outSqr.addEventListener (MouseEvent.ROLL_OVER,sqrOver);
outSqr.addEventListener (MouseEvent.ROLL_OUT,sqrOut);

function sqrOver(e:MouseEvent) {
    inSqr.visible = true;
}

function sqrOut (e:MouseEvent) {
    inSqr.visible = false;
}

答案 2 :(得分:0)

the simpliest solution i can imagine

package {
    import flash.events.MouseEvent;
    import flash.display.Sprite;
    public class FlashTest extends Sprite {
        private var inner:Sprite;
        private var outer:Sprite;
        public function FlashTest() {
            outer = giveRect(200, 200, 0xff0000);
            addChild(outer);
            inner = giveRect(50, 50, 0xffff00);
            addChild(inner);
            inner.x = inner.y = 75;
            stage.addEventListener(MouseEvent.MOUSE_MOVE, onMove);       
        }

        private function giveRect(w:int, h:int, color:int):Sprite{
            var spr:Sprite =  new Sprite();
            spr.graphics.beginFill(color);
            spr.graphics.drawRect(0, 0, w, h);
            spr.graphics.endFill();
            return spr;            
        }

        private function onMove(e:MouseEvent):void{
            inner.visible = stage.mouseX > outer.x &&
                            stage.mouseX < outer.x + outer.width &&
                            stage.mouseY > outer.y &&
                            stage.mouseY < outer.y + outer.height;
        }
    }
}