Javascriptでimage画像にcanvasを使ってレンズフレアとゴーストを加える

Javascriptでimage画像にcanvasを使ってレンズフレアとゴーストを加える

サンプル

<img>タグの画像にレンズフレアとゴーストを適用させます。

未適用
適用
未適用
適用
未適用
適用

ソースコード

<script>
//レンズフレアとゴースト
function MamLensFlare(srcImg,deg,strength,ghostNum){
  let w,h,wh;
  let img=new Image();
  img.src=srcImg.src;
  img.addEventListener("load",function(){
    // canvas.width, canvas.height 内部で持つ画像データのサイズ
    // canvas.style.width, canvas.style.height 実際に表示されるサイズ
    let can=document.createElement("canvas");
    w=img.naturalWidth;
    h=img.naturalHeight;
    wh=(w+h)/2;
    r=(w+h)/2*0.16;
    can.width=w;
    can.height=h;
    let ctx=can.getContext("2d");
    ctx.drawImage(img,0,0);
    if(deg==null){deg=45;}
    deg+=90;
    if(strength==null){strength=0.5;}
    if(strength>1){strength=1.0;}
    if(strength<0){strength=0.0;}
    if(ghostNum==null){ghostNum=5;}
    if(ghostNum<2){ghostNum=2;}
    if(ghostNum>4){ghostNum=4;}

    //レンズフレア
    let xx=w/2-Math.cos(deg/180*Math.PI)*wh*0.45;
    let yy=h/2-Math.sin(deg/180*Math.PI)*wh*0.45;
    let rr=r*(0.8+Math.random()*0.1);
    let st1=0.9+0.1*(strength-0.5);
    let st2=0.2+0.2*(strength-0.5);
    let st3=0.1+0.10*(strength-0.5);
    //円形グラデーション
    let grd=ctx.createRadialGradient(xx,yy,0, xx,yy,rr);
    grd.addColorStop(0.00,'rgba(255,255,255,'+st1+')');
    grd.addColorStop(0.05,'rgba(255,255,255,'+st1+')');
    grd.addColorStop(0.70,'rgba(255,255,255,'+st2+')');
    grd.addColorStop(0.80,'rgba(255,255,255,'+st3+')');
    grd.addColorStop(1.00,'rgba(255,255,255,0.0)');
    ctx.beginPath();
    ctx.arc(xx, yy, rr, 0, 2 * Math.PI);
    ctx.fillStyle = grd;
    ctx.fill();

    //ゴースト
    for(let i=0;i<ghostNum;i++){
      let xx=w/2-Math.cos(deg/180*Math.PI)*wh*(i-(ghostNum)-0.2)/ghostNum*0.6;
      let yy=h/2-Math.sin(deg/180*Math.PI)*wh*(i-(ghostNum)-0.2)/ghostNum*0.6;
      let rr=r*(ghostNum-i)/ghostNum*(0.6+Math.random()*0.1);
      let st1=0.40+0.2*(strength-0.5)+(r-rr)/rr/16;
      let st2=0.20+0.15*(strength-0.5)+(r-rr)/rr/16;
      let st3=0.05+0.10*(strength-0.5)+(r-rr)/rr/16;


      //円形グラデーション
      let grd=ctx.createRadialGradient(xx,yy,0, xx,yy,rr);
      grd.addColorStop(0.0,'rgba(255,255,255,'+st1+')');
      grd.addColorStop(0.7,'rgba(255,255,255,'+st2+')');
      grd.addColorStop(0.9,'rgba(255,255,255,'+st3+')');
      grd.addColorStop(1.0,'rgba(255,255,255,0.0)');
      ctx.beginPath();
      ctx.arc(xx, yy, rr, 0, 2 * Math.PI);
      ctx.fillStyle = grd;
      ctx.fill();
    }
    srcImg.src=can.toDataURL("image/png");
  });
}
window.addEventListener("DOMContentLoaded",function(){
  //MamLensFlare(適用する<img>, 角度[度], 強さ[0~1], ゴースト数[1~4]);
  //角度:↑0度 →90度 ↓180度 ←270度
  MamLensFlare( document.getElementById("img1"), -45, 1.0, 4);
  MamLensFlare( document.getElementById("img2"),  30, 1.0, 4);
  MamLensFlare( document.getElementById("img3"),  53, 0.5, 4);
});
</script>

<img src="./imgs/c064.jpg" id="img1">
<img src="./imgs/c059.jpg" id="img2">
<img src="./imgs/c051.jpg" id="img3">