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

发布于 2024-12-07 14:34:04 字数 1992 浏览 1 评论 0原文

假设我们有一个有两个正方形的舞台,如下所示: 我们的示例 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 周期。 另外,如果红色方块覆盖整个舞台(与舞台尺寸相同)- 它会产生问题(它不起作用)。


有谁知道一种简单优雅的方法来完成此任务 - 一种不会涉及太麻烦和太长的代码,并且不必使用反复进行命中测试的重复计时器......?

Suppose we have a stage with two squares, like so:
Our example Flash stage

Suppose we'd like the yellow square to be initially hidden, and we'd like that as long as the mouse cursor is inside the bounds of the red square - the yellow square will be visible, and as long as the mouse cursor is out of the bounds of the red square - that the yellow square will be hidden.

The intuitive approach is to write something like this:

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

With this code, however - any time you move the mouse cursor to within the yellow square -
it, apparently, counts as a ROLL_OUT for the RED square -
thus the sqrOut function is triggered - making the yellow square disappear, and once the yellow square is not there - the cursor is suddenly within the bounds of the RED square again - so the sqrOver function
gets called - bringing back the yellow square's visibility - triggering sqrOut and so on and so forth, thus creating a "flickering" yellow square when the mouse-cursr is over him:
the yellow square disappears and reappears repeatedly over and over again.

A possible "fix" for this is to remove the listener for the red's roll-out event while the cursor is inside the yellow (if it's inside the yellow it surely is inside the red as well), and bring it back when it is out, by adding this to the code above:

 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);
     }
 }

This works.
But it is cumbersome. You have to do it for each any object inside the bounds of the red square - resulting in long code and many event listeners and continuous listener-registration and unregisteration.

A few years ago someone suggested to me this technique:

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

This is a simple short code that works.
But, if your project doesn't really need to use the ENTER_FRAME event it creates the unnecessary overhead and cpu-cycles of repeatedly running the hit test.
Also, if the red square covers the entire stage (has the same dimensions as the stage) -
it creates problems (it doesn't work).

Is anyone aware of a simple elegant way to accomplish this - one that would not involve too cumbersome and long code and that would not have to use a repeated timer that hit-tests over and over again...?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

桃气十足 2024-12-14 14:34:04

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

outSqr.addChild(inSqr);

这将很好且简单地解决您的问题。只需确保 outSqr 是 SpriteMovieClip 类的实例即可。

Place the yellow square inside the red square.

outSqr.addChild(inSqr);

That will solve your problems nicely and simply. Just be sure outSqr is an instance of the Sprite or MovieClip class.

旧梦荧光笔 2024-12-14 14:34:04

我不知道这对您的情况是否有帮助,但您也可以禁用 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;
}

I don't know if this helps in your case, but you could also disable mouse actions of the inSqr, then you can hover over the yellow square which does not trigger the ROLL_OUT

inSqr.mouseEnabled = false

..then you could just use this:

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;
}
情归归情 2024-12-14 14:34:04

我能想象到的最简单的解决方案

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

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;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文