2014-01-29 175 views
1

我正在將一批150張HD圖像加載到我的應用程序中 - 它基本上是一個對象的3D視圖。一旦我使用Loader實例加載圖像文件,我將加載器的第一個孩子的位圖數據存儲在Vector中。當所有的加載,我想開始「旋轉」的對象=意味着我只是交換圖像。我將矢量放在我有位圖數據的位置,然後依次將它們繪製到畫布位圖數據上。那裏沒有科學,一切都按預期工作。加載圖像不會將它們加載到內存中

問題是,一旦所有的圖像加載並存儲在一個向量中,並且在它們被繪製到畫布之前,它們不在內存中。這意味着3D對象的第一次旋轉( - >所有150個繪製的圖像)非常慢。第一次旋轉後沒有問題,並且都是流體。我的問題是:有沒有辦法強制圖像加載到內存中而不會將它們拖到舞臺上?我預計,一旦它們加載到應用程序,它們就會被加載到內存中(錯誤!)。

我試圖使用addChild()而不是將它們繪製到畫布位圖,結果相同。我不認爲代碼是必要的,但以防萬一:

private var _loaders:Vector.<Loader>; 
private static const NAME:String = "img_00"; 
private static const MIN:uint = 0; 
private static const MAX:uint = 150; 
private var _loaded:uint = 0; 
private var _currentFrameIndex:uint = 0; 
private var _canvas:Bitmap; 
private var _bitmaps:Vector.<BitmapData>; 
private var _destPoint:Point; 

public function loadImages():void { 
    var s:String; 
    for(var i:int=MIN; i<=MAX; i++) { 
     if(i < 10) s = "00" + i; 
     else if(i < 100) s = "0" + i; 
     else s = i.toString(); 
     var loader:Loader = new Loader(); 
     loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadHandler); 
     loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, loadHandler); 
     loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, loadHandler); 
     loader.load(new URLRequest("images/JPEG/"+ NAME + s + ".jpg")); 
     _loaders.push(loader); 
    } 
} 

private function loadHandler(e:Event):void { 
    _loaded++; 

    if(_loaded > (MAX - MIN)) { 
     _bitmaps = new Vector.<BitmapData>(_loaders.length); 
     for(var i:int=0; i<_loaders.length; i++) { 
      var loader:Loader = _loaders[i]; 
      _bitmaps[i] = Bitmap(loader.getChildAt(0)).bitmapData; 
      loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loadHandler); 
      loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, loadHandler); 
      loader.contentLoaderInfo.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, loadHandler); 
     } 
     setFrame(0); 
     dispatchEvent(new Event(LOAD_COMPLETE)); 
    } 
} 

public function setFrame(frame:uint):void { 
    if(frame >= 0 && frame < _bitmaps.length) { 
     _currentFrameIndex = frame; 
     var bmpData:BitmapData = _bitmaps[_currentFrameIndex]; 
     _canvas.bitmapData.copyPixels(bmpData, bmpData.rect, _destPoint); 
    } 
} 

回答

0

「不是在存儲」指的是圖像加載,但尚未被解碼,這解碼是動態完成的,這把你觀察的時間視爲緩慢。您可以嘗試通過將尚未添加到舞臺的位圖作爲對矢量的每個bitmapDatas的引用來「虛擬」旋轉圖像。製作一個進度條,顯示已經解碼了多少矢量,一旦出現這種情況,顯示位圖並給用戶平滑旋轉。

addEventListener(Event.ENTER_FRAME,prerender); 
var b:Bitmap=new Bitmap(); 
/* optional 
    b.x=stage.stageWidth; 
    b.y=stage.stageHeight; 
    addChild(b); 
*/ 
var vi:int=0; 
var sh:Shape=new Shape(); 
sh.graphics.lineStyle(4,0,1); // a simple progress bar 
sh.graphics.moveTo(0,0); 
sh.graphics.lineTo(100,0); 
sh.scaleX=0; 
sh.x=stage.stageWidth/2-50; // centered by X 
sh.y=stage.stageHeight/2; 
addChild(sh); 
function prerender(e:Event):void { 
    if (vi==_bitmaps.length) { 
     // finished prerender 
     removeEventListener(Event.ENTER_FRAME, prerender); 
     removeChild(sh); 
     // removeChild(b); if optional enabled 
     setFrame(0); 
     return; 
    } 
    b.bitmapData=_bitmaps[vi]; 
    vi++; 
} 

此外,它總是最好的bitmapData屬性分配給一個Bitmap對象,如果你不打算讓該BitmapData改變。所以,而不是你的_canvas.bitmapData.copyPixels(bmpData, bmpData.rect, _destPoint);你只是做_canvas.bitmapData = bmpData;,它會工作。

更新:你的問題不妨指出最後一點,即分配而不是複製。如果您的destPoint不是(0,0),則只需在_canvas的頂部再製作一個Bitmap對象,並使用所需的偏移量,然後在其中分配位圖數據。我記得當我第一次製作多個基於像你的單一的動畫對象,並試圖做copyPixels()時,我的動畫抖動並且沒有顯示正確的幀,但是一旦我做了_bitmap.bitmapData=_bitmaps[currentFrame],一切都變得順利。

+0

我猜測它正是這樣 - 圖像還沒有解碼(將解釋內存使用情況和緩慢)。好吧,太糟糕了,我想用戶將不得不等待更多。謝謝! – Fygo

+0

PS:渲染位圖務必在顯示列表上,它必須是可見的。否則它將無法工作,因此在這種情況下,addChild/removeChild看起來不是可選的。 (所以它可以在主畫布上呈現)。 – Fygo

+0

有趣。好吧,我很高興你有這個。 – Vesper