在做游戏地图和其它项目时候需要对png图像的透明部分进行处理,下面对我用过的几种方法做总结。每种方法都有自己的优缺点根据需要使用。
第一种方案是使用InteractivePNG(相对于显示对象处理)
flash上用就不说了官方有例子,在flex上使用需要做稍许改动,只要把extends由MovieClip改成Image就可以了,但是这样改有一个小bug,使用的时候需要注意。在Image指定source时需要指定一个绑定对象而不能使用图像路径的字符串。
[Embed(source="1.png")]
private var background:Class;
<ns1:InteractivePNG x="33" y="31" width="308" height="222" id="img" source="background"/>
第二种通过容器的像素点检测(相对于容器处理)
对容器添加监听鼠标事件
记录鼠标的xy位置,遍历一边所有容器里的显示对象(由于容器对象的Index问题需要反向遍历显示对象),判断该点的alpha是否大于0xff(取颜色的时候需要转换一下坐标系)。
第三种使用碰撞检测(相对于容器处理)
写一个静态方法检测,检测像素级的单击检测,类似与第二种方法。
public static function realHitTest(object:DisplayObject, point:Point):Boolean {
if(object is BitmapData) {
return (object as BitmapData).hitTest(new Point(0,0), 0, object.globalToLocal(point));
}
else {
if(!object.hitTestPoint(point.x, point.y, true)) {
return false;
}
else {
var bmapData:BitmapData = new BitmapData(object.width, object.height, true, 0x00000000);
bmapData.draw(object, new Matrix());
var returnVal:Boolean = bmapData.hitTest(new Point(0,0), 0, object.globalToLocal(point));
bmapData.dispose();
return returnVal;
}
}
}
第四种是用hitArea来实现,网上有现成的例子,就是遍历一边该图像的像素点来重绘图像的hitArea(相对于显示对象本身处理)
如果图像很大估计会很慢
package
{
import flash.display.BitmapData;
import flash.display.DisplayObject;
import flash.display.Sprite;
import flash.events.Event;
import flash.geom.Matrix;
import flash.utils.setTimeout;
import mx.controls.Image;
public class DisplayImage extends Image
{
private var ht:Sprite = new Sprite();
public function DisplayImage()
{
addChild(ht);
hitArea = ht;
//指定hitArea为ht对象
ht.visible = false;
ht.mouseEnabled = false;
mouseChildren = false;
addEventListener(Event.COMPLETE,complete,false,99,true);
setTimeout(update,50)
}
private function complete(e:Event):void
{
setTimeout(update,50)
}
private function update():void
{
if(!content)return;
var loader:DisplayObject = content.parent as DisplayObject;
var bit:BitmapData = new BitmapData(loader.width,loader.height,true,0x00000000);
var mat:Matrix = new Matrix();
mat.scale(loader.scaleX,loader.scaleY);
bit.draw(loader,mat);
//重绘图象到bit
ht.graphics.clear();
ht.graphics.beginFill(0);
for(var x:uint=0;x<bit.width;x++)
{
for(var y:uint=0;y<bit.height;y++)
{
if(bit.getPixel32(x,y))ht.graphics.drawRect(x,y,1,1);
}
}
//以graphics画出bit的无透明区域
ht.graphics.endFill();
}
}
}
总结对于透明检测归根到底还是像素点的检测只是方法变通而已。处理方式分为针对容器和针对显示对象本身两种方式
呵呵,最后再加一个方法,获得“真实”图像大小的方法处理那些有大量空白区域的图像。
public function getBitmapCroppedOutWhitespace(bd:BitmapData):Bitmap {
var rect:Rectangle = bd.getColorBoundsRect(0xFFFFFF, 0x00000000, false);
var bmd2:BitmapData = new BitmapData(rect.width, rect.height, true, 0x00000000);
bmd2.draw(bd, new Matrix(1,0,0,1, -rect.x, -rect.y));
var bmp:Bitmap = new Bitmap(bmd2);
return bmp;
}