如何使用canvas和javascript创建运动模糊效果?

5

我有一个虚拟画布,上面画了一个图标。因为这个图标是动态的,所以我无法在Photoshop中制作一个模糊运动的变体。我通过以下代码在场景中渲染这个图标:

function render (context) {
    context.drawImage(this.bufferedIcon, 0, 0);
}

请问是否有一种简单的方法来创建这个图标的动态模糊效果?


2
使用叠加元素并将其不透明度降低怎么样?您只需要创建一些元素,当不透明度更改时,它会看起来像是模糊的。 - Adjit
1
我认为这并没有帮助。我必须得到图标的动态模糊效果,因为我要模仿图标移动得非常快的样子。我也找到了高斯模糊的算法,但是我找不到一个简单的运动模糊算法。 - Aircraft5
你能展示一下高斯模糊的代码吗?还有一些我们可以尝试的小例子吗? - Adjit
当然可以!但我现在无法完成。我会准备一个好的例子,并明天在这里发布。 - Aircraft5
七年过去了,我仍然没有提供一个好的例子!希望你不会生气!:-D - Aircraft5
1个回答

7

要实现简单的动态模糊效果,可以使用globalAlpha属性。

var ctx = document.getElementById("can").getContext("2d");


// dx and dy is the direction and speed of the blur
function drawBlured(x,y,dx,dy){ // x,y current position, dx,dy delta x,y 
     var samples = 10;  // the number of samples. The greater the number the 
                       // better the effect but the slower the render
                       // over 100 samples and the dynamic range of colours 
                       // will begin to make it look bad
     dx /= samples;   // divide the speed by the number of samples
     dy /= samples;
     ctx.globalAlpha = 1/(samples/1.2);  // set the global alpha need to up the 
                                       // val a bit or it gets to dark
     for(var i = 0; i < samples; i++){  // draw  the image for each sample
         ctx.drawImage(image, x+i*dx,y+i*dy); // moving it as we go
     }
     ctx.globalAlpha = 1;  // restore alpha
} // done;


// code from here down is just for the snippet
var posX= 200;
var posY = 200;
var speedX,speedY
var destX,destY;

// create somthing to blur
var image = document.createElement("canvas");
image.width = 100;
image.height =100;
var ctxS = image.getContext("2d");
ctxS.fillStyle = "Black";
ctxS.beginPath();
ctxS.arc(50,50,48,0,Math.PI*2);
ctxS.fill();

ctxS.beginPath();
ctxS.fillStyle = "#FF0";
ctxS.arc(48,48,44,0,Math.PI*2);
ctxS.fill();

ctxS.fillStyle = "Black";
ctxS.beginPath();
ctxS.arc(25,25,20,0,Math.PI*2);
ctxS.fill();
ctxS.beginPath();
ctxS.arc(75,25,20,0,Math.PI*2);
ctxS.fill();
ctxS.beginPath();
ctxS.arc(50,80,10,0,Math.PI*2);
ctxS.fill();

ctxS.beginPath();
ctxS.fillStyle = "white";
ctxS.arc(25,25,16,0,Math.PI*2);
ctxS.fill();
ctxS.beginPath();
ctxS.arc(75,25,16,0,Math.PI*2);
ctxS.fill();

ctxS.beginPath();
ctxS.fillStyle = "black";
ctxS.arc(25,25,8,0,Math.PI*2);
ctxS.fill();
ctxS.beginPath();
ctxS.arc(75,25,8,0,Math.PI*2);
ctxS.fill();


var moving = false; // when moving
var wait = 10;  // a pause timer
function update(){
  ctx.clearRect(0,0,400,400);  // clear
  if(moving){  // draw moving
    drawBlured(posX,posY,speedX,speedY);
    posX += speedX;
    posY += speedY;
    wait -= 1;
    if(wait <= 0){ // done moving pause
      moving = false;
      wait = Math.random()*10+5;
    }
  }else{
    if(wait > 0){  // wait 
      wait -= 1;
      ctx.drawImage(image,posX,posY);

    }else{ // done waiting find a spot to move
      destX = (Math.random()*300)+50;
      destY = (Math.random()*300)+50;        
      speedX = (destX-posX)/5;
      speedY = (destY-posY)/5;        
      ctx.drawImage(image,posX,posY);
      wait = 5;
      moving = true;   // start movng

    }
  }
  setTimeout(update,50);  // do this 20 times a second
}
update();
.canC {
  width:400px;
  height:400px;
 }
<canvas class="canC" id="can" width=400 height=400></canvas>

不要使用模糊滤镜。它们效率极低,可能在您的电脑上看起来很好,但在许多机器上会导致崩溃和显示不佳。


太棒了!非常感谢! - Aircraft5
点赞支持好的回答。我更喜欢将requestAnimationFrame作为循环。 - markE
2
添加运动模糊在每秒30帧以上的帧速率时存在问题,你根本看不到效果。20FPS是故意设定的,以便能够看到模糊效果。 - Blindman67

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接