通过尽量重复使用实例来优化 BitmapData 类的使用,这一点非常重要。Flash Player 10.1 和 AIR 2.5 引入了一个适用于所有平台的新功能,称为 BitmapData 单个引用。从嵌入图像创建 BitmapData 实例时,将对所有 BitmapData 实例使用位图的同一版本。如果稍后修改位图,则在内存中为该位图提供其自身的唯一位图。嵌入的图像可来自库或 [Embed] 标签。
注:
此新功能同样适用于当前内容,因为 Flash Player 10.1 和 AIR 2.5 会自动重复使用位图。
当实例化嵌入的图像时,将在内存中创建相关联的位图。在 Flash Player 10.1 和 AIR 2.5 之前的版本中,内存中为每个实例都提供了一个单独的位图,如下图所示:
运行 Flash Player 10.1 和 AIR 2.5 之前,内存中的位图
在 Flash Player 10.1 和 AIR 2.5 中,当创建同一图像的多个实例时,单个版本的位图将用于所有 BitmapData 实例。下图演示了此概念:
Flash Player 10.1 内存中的位图 和 AIR 2.5
此方法大大降低了具有许多位图的应用程序的内存使用量。以下代码创建了
Star
符号的多个实例:
const MAX_NUM:int = 18;
var star:BitmapData;
var bitmap:Bitmap;
for (var i:int = 0; i<MAX_NUM; i++)
{
for (var j:int = 0; j<MAX_NUM; j++)
{
star = new Star(0,0);
bitmap = new Bitmap(star);
bitmap.x = j * star.width;
bitmap.y = i * star.height;
addChild(bitmap)
}
}
下图显示该代码的效果:
例如,使用 Flash Player 10 时,上面的动画使用大约 1008 KB 内存。使用 Flash Player 10.1 时,在台式机和移动设备上该动画只使用 4 KB。
以下代码修改一个 BitmapData 实例:
const MAX_NUM:int = 18;
var star:BitmapData;
var bitmap:Bitmap;
for (var i:int = 0; i<MAX_NUM; i++)
{
for (var j:int = 0; j<MAX_NUM; j++)
{
star = new Star(0,0);
bitmap = new Bitmap(star);
bitmap.x = j * star.width;
bitmap.y = i * star.height;
addChild(bitmap)
}
}
var ref:Bitmap = getChildAt(0) as Bitmap;
ref.bitmapData.pixelDissolve(ref.bitmapData, ref.bitmapData.rect, new Point(0,0),Math.random()*200,Math.random()*200, 0x990000);
下图显示修改一个
Star
实例的效果:
在内部,运行时会在内存中自动分配和创建位图以处理像素修改。当调用的 BitmapData 类的方法导致像素修改时,将在内存中创建一个新实例,而不更新其他实例。下图演示了此概念:
修改一个位图后,内存中的效果
如果修改一个星星,则在内存中创建一个新的副本。在 Flash Player 10.1 和 AIR 2.5 上,生成的动画使用大约 8 KB 内存。
在上一示例中,各个位图可单独用于转换。要仅创建平铺效果,则
beginBitmapFill()
方法是最合适的方法:
var container:Sprite = new Sprite();
var source:BitmapData = new Star(0,0);
// Fill the surface with the source BitmapData
container.graphics.beginBitmapFill(source);
container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
addChild(container);
此方法与仅创建一个 BitmapData 实例的效果相同。要连续旋转星形,请使用绕各个帧旋转的 Matrix 对象,而不是访问各个 Star 实例。将此 Matrix 对象传递给
beginBitmapFill()
方法:
var container:Sprite = new Sprite();
container.addEventListener(Event.ENTER_FRAME, rotate);
var source:BitmapData = new Star(0,0);
var matrix:Matrix = new Matrix();
addChild(container);
var angle:Number = .01;
function rotate(e:Event):void
{
// Rotate the stars
matrix.rotate(angle);
// Clear the content
container.graphics.clear();
// Fill the surface with the source BitmapData
container.graphics.beginBitmapFill(source,matrix,true,true);
container.graphics.drawRect(0,0,stage.stageWidth,stage.stageHeight);
}
借助此技术,无需 ActionScript 循环即可创建这种效果。运行时在内部执行所有操作。下图显示转换星形的效果:
借助此方法,更新原始的源 BitmapData 对象时将自动更新其在舞台上的所有使用,这可能是一项功能强大的技术。然而,此方法不允许单独缩放各个星形,如前面的示例中所示。
注:
当使用同一图像的多个实例时,将根据某个类是否与内存中的原始位图相关联进行绘图。如果不存在与位图相关联的类,则图像将作为 Shape 对象使用位图填充进行绘制。