Actionscript 3 防止透明位图精灵的边界框触发鼠标事件
我以为我已经解决了包含alpha通道位图的精灵的mouseEvent问题,但我遇到了下图所示的新问题:“欧亚”地图精灵的边界框正在触发“非洲”精灵的“mouseEvent.Roll_Out” 我的设置:每个贴图块都是一个精灵,带有一个子位图(带有alpha的PNG)和一个“hitArea”“从位图派生的精灵。相关代码如下。这非常有效——除了边界框重叠的情况。我附加到每个精灵的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
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
容器)另外,我正在使用GreensockTransformManager
,混合位图和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
}