最佳化 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 物件一樣的影像並將點陣圖填色。