我正在尝试将全屏幕背景图像加载到画布上,然后将图像过滤器应用于它,但有一些问题。我遇到了严重的性能问题,但只有在调整窗口大小时。基本上,我的代码试图使画布/图像匹配屏幕尺寸(效果很好)。
更新画布方法:
在LOAD上调用UpdateCanvas方法最初创建/加载图像对象并将其放在画布上。如果选择过滤器,它将调用过滤器方法。它接受onResize参数,该参数通过窗口大小在窗口大小上传递以扩展画布/图像。主要是指用于引用元素的对象。
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
};
};
};
画布过滤器方法:如果要将图像过滤器应用于背景图像,则从canvasupdate方法调用CanvasFilter方法。
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));
};
所有这些都可以使用,初始绘制/过滤器非常快。但是,当我调整窗户大小时,它非常缓慢。我暂时通过放入油门来解决这个问题,这只是设置了一个计时器,以避免射击上述功能过快。这会稍微有所帮助,但会将背景图像保持在适当的位置(在图像周围显示开放的背景区域),直到油门计时器启动并启动方法 - 调整帆布/图像并应用过滤器。
问题:
有更快的方法吗?我已经阅读了有关将键入阵列/钻头用于像素操作循环的有关的,但似乎支持这是可怕的。我还研究了CSS3过滤器来完成同样的事情,但是再次,支持是可怕的。因此,这将是使用" Modern Browser"兼容性的全屏背景图像过滤器的唯一方法?
UpdateCanvas方法每次都会创建一个新的图像对象,我认为这可能是瓶颈,但不确定,并且不确定如何解决它?
我已经阅读了其他用单独的画布作为缓冲区的读书?这实际上会增加我的情况吗?
我真的认为我的代码中存在一个主要的逻辑问题。对我来说,我需要不止一次循环浏览所有像素信息,这是没有意义的,但这是我唯一可以使用它的方法。我没有一种方法可以绘制它/应用一次过滤器,然后在调整大小上,只需调整尺寸而无需重新绘制/reloop/重新涂抹过滤器吗?我认为它将维护过滤后的图像,但是如果我在窗口大小上删除对CanvasFilter方法的调用,则完全消除了过滤器效果。
我尚未使用回忆技术,因为我从未完全理解过它,并且从未完全理解在哪里/何时使用它。但是,从本质上讲,如果我的函数一次又一次返回相同的结果(例如CanvasFilter方法),我可以记住以提高性能 - 还是会有所不同,因为它在窗口大小后会提取不同的像素信息?<<<</p>
我还听说WebGL渲染可能会有所帮助吗?我对WebGL一无所知,可能会遥遥无期。
对这个问题很抱歉,但希望这涵盖了其他人也可以从中受益的一些主题。任何建议/提示都将不胜感激。谢谢!:)
,因为听起来您的图像大多是静态的,因此您可能想尝试的一种方法是使用良好的旧CSS。
这里的关键技巧是使用背景大小:封面。请参阅:http://css-tricks.com/perfect-full-page-background-image/
如此广义:
- 加载图像
- 将过滤器应用于画布。(甚至不需要将画布附加到页面上)。
- 将您的画布数据导出为URL:
ctx.toDataUrl("image/png");
- 将样式添加到您的容器元素或身体中:
background-size:cover;background:url('data:image/png;yourcanvasdata');
- 通过JS或CSS过渡属性来动画容器元素/主体的不透明度