如何检查鼠标是否可点击?

时间:2010-01-06 22:57:08

标签: flash actionscript-3

我正在构建一个加载外部SWF的专用查看器应用程序。

var content:Sprite = ...
content.addChild(loader);

我会收听我的顶级内容Sprite MOUSE_OVER和MOUSE_OUT事件。 over处理程序隐藏默认光标并显示自定义(缩放)光标。 Out处理程序将光标更改回默认值。

我想要实现的是当鼠标悬停在外部加载的SWF中的可点击项目(如按钮或文本链接)上时,不显示缩放光标。

当前代码适用于AVM1 swfs。 问题在于使用AS3加载的swfs。 对于这些内容,MOUSE_OUT被触发并且立即触发MOUSE_OVER,因此光标仍然是错误的。

这可能归结为:如何检查鼠标是否在内容的可点击子项上?

2 个答案:

答案 0 :(得分:4)

好问题!

我做了一个快速测试。有一种名为getObjectsUnderPoint()的方法

  

返回一个谎言对象数组   在指定点下并且是   孩子(或孙子孙女等)   这个DisplayObjectContainer   实例

根据文件。

另外

  

任何子对象   因安全原因无法访问   从返回的数组中省略。至   判断这是否安全   限制影响返回   数组,调用   areInaccessibleObjectsUnderPoint()   方法

所以我不知道这有多大帮助。

不过,这是我的测试:

//make some clips interactive
for(var i:int = 0 ; i < numChildren ; i+=2){
    MovieClip(getChildAt(i)).mouseEnabled = true;
    MovieClip(getChildAt(i)).buttonMode = true;
    MovieClip(getChildAt(i)).mouseChildren = false;
}
//reuse this array
var clips:Array;
addEventListener(Event.ENTER_FRAME, checkClickables);
function checkClickables(event:Event):void {
    clips   = this.getObjectsUnderPoint(new Point(mouseX,mouseY));
    for(i = 0 ; i < clips.length ; i++){
        if(isInteractiveObject(clips[i])){
            trace(clips[i]);
        }
    }
}
function isInteractiveObject(object:*):Boolean{
    var extendsClass:XMLList = describeType(object).extendsClass;
    for each(var classDef:XML in extendsClass){
        if(classDef.@type == 'flash.display::InteractiveObject') return true;
    }
    return false;
}

我在舞台上有一些片段,我正在制作一些“可点击”的片段。 然后onEnterFrame我正在检查是否有子类的任何实例 InteractiveObject(任何可点击的超类)

出于某种原因,在我的测试中,getObjectsUnderPoint()只返回Shape对象,没有Sprite。 也许它可能适用于您的配置。

这似乎有点复杂。

这是我的第二种方法:

function getInteractiveObjects(container:DisplayObjectContainer):Array{
    var result:Array = [];
    for(var i:int = 0 ; i < container.numChildren ; i++){
        if(container.getChildAt(i) is Sprite || container.getChildAt(i) is MovieClip) result.push(container.getChildAt(i));
        if(container.getChildAt(i) is DisplayObjectContainer){
            var clips:Array = getInteractiveObjects(DisplayObjectContainer(container.getChildAt(i)));
            var clipsNum:int = clips.length;
            for(var j:int = 0 ; j < clipsNum ; j++)
                if(clips[j] is Sprite || clips[j] is MovieClip) result.push(clips[j])
        }
    }
    return result;
}

使用递归函数在剪辑中获取潜在的交互式目标(如加载程序内容)。如果它是Sprite或MovieClip,则它是“可点击的”。

var iclips:Array = getInteractiveObjects(this);
for(i  = 0 ; i < iclips.length ; i++){
    trace(iclips[i].name);
    //do extra tests here
    if(iclips[i].hasEventListener(MouseEvent.ROLL_OVER)) trace(iclips[i].name + ' has roll over');
    //etc.
}

然后你可以进行额外的测试,具体取决于你正在寻找什么(它有鼠标事件和事件监听器,它是mouseEnabled,buttonMode设置为true等等)。

这样你就不需要检查任何鼠标悬停(不必等待用户交互或一直调用一个函数),一旦你得到的剪辑不符合你想要的方式,你可以改变他们的行为(mouseChildren = false,或者什么)。

HTH

答案 1 :(得分:0)

通过一些测试以及George给我的提示,这是我刚刚写的内容MOUSE_OVER听众(在Haxe中)似乎有效:

public var mouseOverClickableContent:Bool;

private function onOverContentChild(event)
{   
    mouseOverClickableContent = false;
    if (event.target != content)
    {
        var obj:flash.display.InteractiveObject = cast event.target;

        while (obj != content)
        {
            if (   obj.hasEventListener(flash.events.MouseEvent.CLICK)
                || obj.hasEventListener(flash.events.MouseEvent.MOUSE_UP)
                || obj.hasEventListener(flash.events.MouseEvent.MOUSE_DOWN)
                || ( Std.is(obj, Sprite) && cast(obj, Sprite).buttonMode )
            ){
                mouseOverClickableContent = true;
                break;
            }
            obj = obj.parent;
        }
    }


}

不幸的是,似乎无法检测鼠标是否在TextField htmlText链接上,因此我可以在那里添加TextField htmlText.indexOf("<a") != -1检查。

除非有人知道检测鼠标在文本字段链接上的技巧吗?