BitmapData 單一參考

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