Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
HTML5画布图像过滤器滞后(JavaScript)_Javascript_Html_Loops_Canvas_Filter - Fatal编程技术网

HTML5画布图像过滤器滞后(JavaScript)

HTML5画布图像过滤器滞后(JavaScript),javascript,html,loops,canvas,filter,Javascript,Html,Loops,Canvas,Filter,我试图将一个全屏背景图像加载到画布上,然后对其应用图像过滤器,但有几个问题。我遇到了严重的性能问题,但只是在调整窗口大小时。基本上,我的代码试图保持画布/图像与屏幕尺寸匹配(这很好) 更新画布方法: updateCanvas方法在加载时被调用,以最初创建/加载图像对象并将其放置在画布上。如果选择了筛选器,它将调用筛选器方法。它接受onResize参数,该参数在调整窗口大小时传递以缩放画布/图像。MAIN是指用于引用元素的对象 updateCanvas:function(onResize){

我试图将一个全屏背景图像加载到画布上,然后对其应用图像过滤器,但有几个问题。我遇到了严重的性能问题,但只是在调整窗口大小时。基本上,我的代码试图保持画布/图像与屏幕尺寸匹配(这很好)

更新画布方法:

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
         };     
    };
};
所有这些都有效,并且初始绘制/过滤速度非常快。然而,当我调整窗口大小时,它非常缓慢。我通过设置一个节流器暂时解决了这个问题,它只是设置了一个计时器,以避免过快地启动上述功能。这有点帮助,但会将背景图像保持在原位(在图像周围显示打开的实心背景区域),直到节流计时器启动并触发方法-调整画布/图像的大小并应用过滤器

问题:

  • 有没有更快的办法?我已经读过关于使用类型化数组/按位进行像素操作循环的文章,但是对于这方面的支持似乎很糟糕。我也研究了CSS3过滤器来完成同样的事情,但同样,支持是可怕的。那么,这是实现与“现代浏览器”兼容的全屏背景图像过滤器的唯一方法吗

  • updateCanvas方法每次都会创建一个新的图像对象,我认为这可能是一个瓶颈,但我不确定,也不确定如何绕过它

  • 我读过其他使用单独画布作为缓冲区的文章吗?在我的情况下,这真的会提高性能吗

  • 我真的认为我的代码中有一个主要的逻辑问题。对我来说,我需要多次遍历所有像素信息是没有意义的,但这是我让它工作的唯一方法。是否有一种方法可以让我绘制/应用过滤器一次,然后调整大小,只需调整尺寸,而无需重新绘制/重新oop/重新应用过滤器?我认为它会保持过滤后的图像,但是如果我在窗口调整大小时删除对canvasFilter方法的调用,它会完全删除过滤效果

  • 我还没有使用记忆技术,因为我从来没有完全理解它,也从来没有完全理解在哪里/什么时候使用它。但是,从本质上讲,如果我有一个函数一次又一次地返回相同的结果(例如canvasFilter方法),我可以通过记忆来提高性能吗?或者,它是否会有所不同,因为它在调整窗口大小后提取不同的像素信息

  • 我还听说webGL渲染可能对此有所帮助?可能太离谱了,因为我对webGL一无所知


  • 很抱歉,这是一个龙龙的问题,但希望这能涵盖一些其他人也能从中受益的话题。如有任何建议/提示,将不胜感激。谢谢!:)

    因为听起来您的图像大多是静态的,所以您可能希望尝试使用好的旧css

    这里的关键技巧是使用背景大小:封面。见:

    因此,广义而言:

  • 加载你的图像
  • 在画布中应用过滤器。(画布甚至不需要附加到页面)
  • 通过以下方式将画布数据导出为url:
    ctx.toDataUrl(“image/png”)
  • 将样式添加到容器元素或主体:
    背景尺寸:封面;背景:url('data:image/png;yourcanvasdata')
  • 通过js或css转换属性设置容器元素/主体的不透明度动画

  • 我是否正确地理解了加载时的所有行为,只是调整窗口大小是个问题?如果是,为什么要重新绘制画布,而不是使用canvas.style.width=“1234px”调整大小?如果没有,在线版本将有助于理解,因为您似乎期望获得上文未描述的独特效果。对于其他画布绘制循环,您可能还需要阅读有关window.requestAnimationFrame的信息。基本上,浏览器会让你知道什么时候可以工作,而不是等待任意的时间。看:很好!这听起来很棒,我对画布操作还是相当陌生,不知道.toDataUrl。听起来很完美:)
    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));
    };