我試圖將全屏背景圖像加載到畫布上,然後將圖像過濾器應用到它,但有幾個問題。我遇到嚴重的性能問題,但只有在調整窗口大小時纔會發生。基本上,我的代碼試圖保持畫布/圖像匹配屏幕尺寸(效果很好)。HTML5畫布圖像過濾器延遲(JavaScript)
UPDATE帆布方法:
的updateCanvas方法稱爲負載到最初創建/加載圖像對象,並將其放置在畫布上。如果選擇了過濾器,則會調用過濾器方法。它接受onResize參數,該參數通過窗口大小調整來縮放畫布/圖像。 MAIN是指用於引用元素的對象。
updateCanvas:function(onResize){
// SETUP VARIABLES
var img=new Image(),
$this=Main.currentOBJ, // REFERENCE FOR .DATA
objData=$this.data,
canvas=Main.OBJ.$Canvas[0],
ctx=canvas.getContext("2d"),
winW=$(window).width(), winH=$(window).height();
// SOURCE CAN BE SET IN .DATA OR DEFAULT
img.src=(objData.bg_pic_src!=='') ? objData.bg_pic_src : Main.ConSRC;
// LOAD THE IMAGE OBJECT
img.onload=function(){
var imgW=img.width, imgH=img.height,
ratio=imgW/imgH, newW=winW, newH=Math.round(newW/ratio);
// SETUP IMAGE PROPORTIONS
if(newH < winH){ var newH=winH, newW=Math.round(newH*ratio); };
// WHEN RESIZING THE BROWSER
if(!onResize){ // INTIAL DRAW
Main.OBJ.$Canvas.attr({'width':newW+'px', 'height':newH+'px'});
ctx.drawImage(img,0,0,newW,newH);
// APPLY FILTERS
if(objData.bg_pic_filter > 0){
Main.canvasFilter(ctx,newW,newH); // FILTER METHOD
}else{
Main.OBJ.$OverlayPic.animate({opacity:parseFloat(objData.bg_pic_opacity,10)},
{duration:objData.bg_pic_speed_in,queue:false});
};
}else{ // RESIZING
Main.OBJ.$Canvas.attr({'width':newW+'px', 'height':newH+'px'});
ctx.drawImage(img,0,0,newW,newH);
if(objData.bg_pic_filter > 0){
Main.canvasFilter(ctx,newW,newH); // FILTER METHOD
};
};
};
畫布篩選方法: 如果圖像濾波程序待應用於背景圖像,所述方法canvasFilter從canvasUpdate方法調用。
canvasFilter:function(ctx,width,height){
// SETUP VARIABLES
var objData=Main.currentOBJ.data,
canvasWidth=width, canvasHeight=height,
imgdata=ctx.getImageData(0, 0, canvasWidth, canvasHeight),
pix=imgdata.data, l=pix.length;
// APPLY THE CORRECT LOOP DEPENDING UPON THE FILTER NUMBER
switch(objData.bg_pic_filter){
case 1: ... break;
case 2:
for(var i=l; i>0; i-=4){
var cacher=pix[i+2];
pix[i]=pix[i+1];
pix[i+1]=cacher;
pix[i+2]=cacher;
pix[i+3]=cacher;
};
break;
};
// APPLY THE FILER & FADE IN THE BACKGROUND
ctx.putImageData(imgdata, 0, 0);
Main.OBJ.$OverlayPic.fadeTo(parseInt(objData.bg_pic_speed_in,10),
parseFloat(objData.bg_pic_opacity,10));
};
所有這些工作,並且初始繪製/過濾器相當快。但是,當我調整窗口大小時,它非常緩慢。我暫時通過加入一個節流器來解決這個問題,它只是設置一個計時器來避免上述功能太快。這稍微有所幫助,但會保留背景圖像(顯示圖像周圍的開放固體背景區域),直到調節器計時器啓動並觸發方法 - 調整畫布/圖像大小並應用過濾器。
問題:
有一個更快的方法?我已經閱讀過使用Typed Arrays/Bitwise進行像素操作循環的問題,但似乎支持對此很可怕。我也研究過CSS3過濾器來完成同樣的事情,但是再一次,支持是非常可怕的。那麼,這是否將成爲全屏幕背景圖像過濾器與「現代瀏覽器」兼容性的唯一方法?
updateCanvas方法每次創建一個新的圖像對象,我想這可能是一個瓶頸,但我不確定,也不確定如何解決它?
我讀過其他人使用單獨的畫布作爲緩衝區?這實際上會提高我的表現嗎?
我真的認爲在我的代碼中有一個主要的邏輯問題。對我來說,我需要不止一次地遍歷所有的像素信息,但這是我獲得它的唯一方法。是不是有一種方法可以繪製/應用過濾器一次,然後調整大小,只需調整尺寸而無需重新繪製/重新放置/重新應用過濾器?我認爲它會保持過濾後的圖像,但如果我在窗口大小調整中刪除了對canvasFilter方法的調用,它將完全刪除過濾器效果。
我還沒有使用memoization技術,因爲我從來沒有完全理解它,並從來不明白何時何地使用它。但是,從本質上講,如果我有一個一次又一次返回相同結果的函數(例如canvasFilter方法),我可以記憶以提高性能 - 或者它會有所不同,因爲它在窗口調整大小後拉動不同的像素信息?
我也聽說webGL渲染可能有幫助嗎?因爲我對webGL一無所知,可能會走開。
所以對於這個loooonng問題感到抱歉,但希望這涵蓋了其他人可以從中受益的一些主題。任何建議/提示將不勝感激。謝謝! :)
我是否正確理解加載時的所有行爲,只是調整窗口大小就是問題所在?如果是,爲什麼你重畫畫布而不是用canvas.style.width =「1234px」調整大小?如果不是這樣,一個在線版本將有助於理解,因爲您似乎期望上面沒有描述的獨特效果。 – noiv
對於其他畫布繪製循環,您可能還需要閱讀有關window.requestAnimationFrame的內容。基本上,瀏覽器會讓你知道什麼時候可以工作,而不是等待任意時間。參見:http://paulirish.com/2011/requestanimationframe-for-smart-animating/ –