2

我已经使用画布标签完成了一个小的全屏背景覆盖,但已经碰到了性能墙。我所做的是创建一个名为#OverlayPic 的容器并将其设置为100% x 100%,显示:无。这个容器里面是我的画布元素。

触发时,jQuery 将图像加载到画布上并将像素信息作为数组获取。switch 语句接受用户为他们想要的过滤效果设置的选项。代码一切正常,但速度非常慢(我认为这主要是由于我的结构方式,但我不确定更好的方法)。

updateCanvas:function(onResize){
    var img=new Image(); img.src=Main.ConSRC,
    img.onload=function(){
        var canvas=document.getElementById('Box_Canvas'),  
            ctx=canvas.getContext("2d"),
        winW=$(window).width(), winH=$(window).height(), 
            imgW=this.width, imgH=this.height, smallestSide=Math.min(imgW,imgH);

    // SETUP IMAGE PROPORTIONS
    switch(smallestSide){
       case imgW: 
           var width=winW,height=width*(imgW/imgH);
           if(height < winH){ var height=winH, width=height*(imgW/imgH); };
        break;
        case imgH: 
           var height=winH,width=height*(imgW/imgH);
           if(width < winW){ var width=winW, height=width*(imgH/imgW); };
        break;
    };

        // DRAW IMAGE ON THE CANVAS
        ctx.clearRect(0, 0, width*1.3, height*1.3 );
    ctx.drawImage(img,0,0,width*1.3,height*1.3);

    // IMAGE FILTERS
    var imgdata=ctx.getImageData(0, 0, width, height), pix=imgdata.data, l=pix.length;
    switch($this.data.bg_pic_filter){
          // all filter code cases are here...
    };          

    // APPLY THE FILER
    ctx.putImageData(imgdata, 0, 0);

    // FADE IN OVERLAY
    if(!onResize){
           Main.OBJ.$OverlayPic.fadeTo( $this.data.bg_pic_speed, $this.data.bg_pic_opacity);
        };

    };
},

这个函数在 2 个地方被调用。

  1. 当用户单击分配的元素时,叠加层会淡入,并且画布会加载过滤后的图像。

  2. 在窗口调整大小事件(onResize arg)上,为了保持所应用的过滤器,否则它只是默认返回原始图像?

有人有任何优化建议吗?谢谢!

4

1 回答 1

1

嗯,你看,你有一个巨大的图像,即使它只有 600x600,它仍然是 36,000 像素,所以即使你//all filter code cases are here...有类似的东西

case default:
   var totalPixels = imagedata.data.length * .25; //divide by 4 now, since dividing is expensive compared to multiplication ( multiply by a decimal place is sometimes cheaper than dividing using /, most browsers have fixed this though[ this is important if you need to know multiple colors at once ] )
   _data = imagedata.data
   for( var i = totalPixels-1; i>=0; i-- ){

     var index = i * 4 // this might be slower (creating a variable inside the loop) -- see next 2 lines

     _data[i * 4] += 1 // these next 2 lines are identical
     _data[index] += 1 // it might be faster to create an index, so you don't have to multiply, though usually multiplying is cheap and creating a variable inside a loop is expensive, so even if you have to multiple i * 4 a bunch, it might be faster than creating index

      _data[index + 1] +=2 //green
      _data[index + 2] +=2 //blue
      _data[index + 3] +=2 //blue

   }

所以,如你所见,你做了多次 3600 次 X 4 次(每个像素 1 次)

这就是测试很重要的地方——比较相同的东西在不同浏览器中的性能提升

使用 / 4 除有时比乘以小数 * .25 如果除以 2 的倍数(例如 x / 2),则可以执行 x >> 1 或 x << 1,称为按位移位一些浏览器已经大大加强了它们的乘法,以至于实际上不再这样做了(chrome)

综上所述,假设您不能使用 web gl 着色器。看,到目前为止,我们已经有了一个函数来循环遍历每个像素,一次 1 个,通过处理器,这是单线程的,而且速度很慢。

来自https://github.com/mrdoob/three.js/ - THREE.js,它允许您使用着色器,因此您可以通过视频卡一次渲染多个像素,这确实是唯一的方法当您必须触摸每个像素时获得更快的速度。这需要一个支持 webGL 的浏览器,这意味着无论如何你都可能支持画布,所以希望这个答案有效。

于 2012-10-19T16:09:21.620 回答