Actionscript 3 防止透明位图精灵的边界框触发鼠标事件

Actionscript 3 防止透明位图精灵的边界框触发鼠标事件,actionscript-3,apache-flex,flex4,Actionscript 3,Apache Flex,Flex4,我以为我已经解决了包含alpha通道位图的精灵的mouseEvent问题,但我遇到了下图所示的新问题:“欧亚”地图精灵的边界框正在触发“非洲”精灵的“mouseEvent.Roll_Out” 我的设置:每个贴图块都是一个精灵,带有一个子位图(带有alpha的PNG)和一个“hitArea”“从位图派生的精灵。相关代码如下。这非常有效——除了边界框重叠的情况。我附加到每个精灵的eventListeners使用MouseEvent.ROLL\u OVER和MouseEvent.ROLL\u OUT

我以为我已经解决了包含alpha通道位图的精灵的mouseEvent问题,但我遇到了下图所示的新问题:“欧亚”地图精灵的边界框正在触发“非洲”精灵的“mouseEvent.Roll_Out”

我的设置:每个贴图块都是一个精灵,带有一个子位图(带有alpha的PNG)和一个“hitArea”“从位图派生的精灵。相关代码如下。这非常有效——除了边界框重叠的情况。我附加到每个精灵的
eventListeners
使用
MouseEvent.ROLL\u OVER
MouseEvent.ROLL\u OUT
但我也尝试了
MouseEvent.MOUSE\u OVER
MouseEvent.MOUSE\u OUT

我曾尝试将eventlisteners附加到“hitArea”精灵和其他各种东西,但我无法忽略边界框。是否有我可能错过的设置或解决方法


代码:

buttonImage = new Bitmap(upImageData);
buttonImage.smoothing = true;
this.addChild(buttonImage);
hitSprite = createHitArea(upImageData, 4);
this.addChild(hitSprite);
hitSprite.visible = false;
hitSprite.mouseEnabled = false;
this.hitArea = hitSprite;

公共函数createHitArea(bitmapData:bitmapData,grainSize:uint=1):精灵
{   
var_hitarea:Sprite=新Sprite();
_hitarea.graphics.beginll(0x000000,1.0);

对于(var x:uint=0;x如果使用向量掩码不是可行的选项(如果您将
hit
更改为
Shape
,然后使其成为地图块精灵的掩码,则该选项应该有效-您还必须将其添加为地图块的同级,而不是子级),大多数人这样做的方式是检查鼠标下的像素是否透明

以下是一个例子:

假设您的所有贴图块都是名为
container
的变量中引用的精灵的唯一子对象。我们还假设您的所有贴图块都是以png位图作为最底层子对象的精灵

您需要将单击侦听器添加到容器(而不是每个单独的映射块):


大多数人通过以下两种方式解决此问题:a:-使用矢量遮罩遮罩剪辑(尽管对于可能会因形状复杂而引起性能问题的贴图)或者b:在鼠标点击处理程序上,确定鼠标点下的像素是否透明。你可以使用方法A,但只需画出一个简单的向量掩模,该掩模接近贴图形状,而不需要太复杂的向量纹理,因此这是一个“已知问题”诸如此类的事情?我以为我用hitarea from bitmap方法在家里是免费的,它工作得很好——除了这个边界框问题。不能使用方法“a”:这些位图是用户在运行时从.psd文件导入的。我已经看过“check pixel”方法的演示——我想我会尝试一下。是的,鼠标侦听器只使用边界(矢量掩码除外)@Batman-不,还没有。它很复杂,因为它在Flex中,所以我必须将我的AS3类包装在
Spark组中(使用
SpriteVisualElement
容器)另外,我正在使用Greensock
TransformManager
,混合位图和SWF–有很多因素在起作用。仅AS3的测试效果很好。尝试不必接触太多这个遗留Flex项目,但看起来我可能不得不这么做。
    public function createHitArea(bitmapData:BitmapData, grainSize:uint=1):Sprite
    {   
        var _hitarea:Sprite = new Sprite();
        _hitarea.graphics.beginFill(0x000000, 1.0);         
        for(var x:uint=0;x<bitmapData.width;x+=grainSize) {
            for(var y:uint=grainSize;y<bitmapData.height;y+=grainSize) {                    
                if(x<=bitmapData.width && y<=bitmapData.height && bitmapData.getPixel(x,y)!=0) {
                    _hitarea.graphics.drawRect(x,y,grainSize,grainSize);
                }                   
            }
        }           
        _hitarea.graphics.endFill();
        _hitarea.cacheAsBitmap = true;
        return _hitarea;
    }
container.addEventListener(MouseEvent.CLICK,click);

function click(e:MouseEvent):void {
    var child:Sprite; //a helper var to store the current iterations child below in the while loop
    var target:Sprite; //the item that we determined was clicked

    //iterate through all children of container (backwards, so we process the top most layer first)
    var i:int = container.numChildren;
    while(i--){
        child = container.getChildAt(i) as Sprite; //populate the child var

        //now we check if the mouse is over this child by a simple hit test point
        //we also then check if the pixel under the mouse is transparent (a value of 0)
        if(child.hitTestPoint(e.stageX, e.stageY) && Bitmap(child.getChildAt(0)).bitmapData.getPixel32(child.x + e.localX,child.y + e.localY)){
            target = child;
            break; //break out of the loop since we found a child that meets the criteria
        }
    }

    trace(target);

    //now do something with target
}