Javascriptでcanvasに花火アニメーションを描画します。Sin、Cosで座標を計算して描画しています。
HTML,Javascript
<canvas class="Hanabi" style="width:100%;max-width:800px;height:200px;"></canvas> <script> TMamHanabi=function(){ this.can=[]; this.ctx=[]; this.width=[]; this.height=[]; this.position=[]; this.basewh=[]; this.basesp=[]; this.limit=[]; this.flag=[]; this.child=[]; this.init=function(){ this.can=document.querySelectorAll(".Hanabi"); for(let i=0;i<this.can.length;i++){ this.ctx[i]=this.can[i].getContext("2d", {willReadFrequently:true}); //見た目のサイズを取得 let style = window.getComputedStyle(this.can[i]); this.width[i]=parseInt(style.width); this.height[i]=parseInt(style.height); this.basewh[i]=Math.min(this.width[i],this.height[i]); this.basesp[i]=this.height[i]/200; //内部のサイズの設定 this.can[i].setAttribute("width",this.width[i]+"px"); this.can[i].setAttribute("height",this.height[i]+"px"); this.position[i]=[]; this.position[i]["x"]=this.width[i]/2; this.position[i]["y"]=this.height[i]; this.limit[i]=this.height[i]*1/3+Math.random()*this.height[i]/3-this.height[i]/6; this.flag[i]=0; this.child[i]=[]; this.reset(i); this.ctx[i].fillStyle="#000"; this.ctx[i].fillRect(0,0,this.width[i],this.height[i]); } window.addEventListener("resize",this.resize.bind(this)); } this.resize=function(){ for(let i=0;i<this.can.length;i++){ //見た目のサイズを取得 let style = window.getComputedStyle(this.can[i]); this.width[i]=parseInt(style.width); this.height[i]=parseInt(style.height); this.basewh[i]=Math.min(this.width[i],this.height[i]); this.basesp[i]=this.height[i]/200; this.can[i].setAttribute("width",this.width[i]+"px"); this.can[i].setAttribute("height",this.height[i]+"px"); } } this.reset=function(i){ this.position[i]["x"]=this.width[i]/3+this.width[i]*Math.random()/3; this.position[i]["y"]=this.height[i]; this.limit[i]=this.height[i]*1/3+Math.random()*this.height[i]/3-this.height[i]/6; this.flag[i]=0; let ct=0; for(let j=0;j<12;j++){ for(let k=0;k<(j+1)*8;k++){ let deg=360/((j+1)*8); this.child[i][ct]=[]; this.child[i][ct]["x"]=this.position[i]["x"]; this.child[i][ct]["y"]=this.limit[i]; let rd=Math.random(); this.child[i][ct]["vx"]=Math.cos(deg*k*Math.PI/180)*(j+0.8+rd*Math.random()*0.4)*this.basewh[i]/640/5; this.child[i][ct]["vy"]=Math.sin(deg*k*Math.PI/180)*(j+0.8+rd*Math.random()*0.4)*this.basewh[i]/640/5; let rr,gg,bb; rr=Math.floor(Math.random()*j/2+255-j*2); gg=Math.floor(Math.random()*j/4+255-j*8); bb=Math.floor(Math.random()*j/16+255-j*16); this.child[i][ct]["c"]=''+rr+','+gg+','+bb+''; ct++; } } } this.draw=function(){ for(let i=0;i<this.ctx.length;i++){ this.ctx[i].fillStyle="#000"; this.ctx[i].fillRect(0,0,this.width[i],this.height[i]); if(this.flag[i]==0){ if(this.position[i]["y"]<this.limit[i]){ this.flag[i]=1; }else{ this.position[i]["y"]-=this.basesp[i]; } let x=this.position[i]["x"]; let y=this.position[i]["y"]; let r=this.basewh[i]/80+Math.random()*this.basewh[i]/80; var rgrd = this.ctx[i].createRadialGradient(x, y, r, x, y, 0); let rr=Math.floor(Math.random()*5+250); let gg=Math.floor(Math.random()*55+200); let bb=Math.floor(Math.random()*55+200); rgrd.addColorStop(0.0, 'rgba('+rr+','+gg+','+bb+',0.0)'); rgrd.addColorStop(0.2, 'rgba('+rr+','+gg+','+bb+',0.2)'); rgrd.addColorStop(1.0, 'rgba('+rr+','+gg+','+bb+',0.8)'); this.ctx[i].beginPath(); this.ctx[i].arc(x, y, r, 0, 2 * Math.PI); this.ctx[i].fillStyle = rgrd; this.ctx[i].fill(); }else if(this.flag[i]>0){ if(this.flag[i]>100){this.flag[i]=-50;return;} var r; for(let j=0;j<this.child[i].length;j++){ r=(1+Math.random()/2)*this.basewh[i]/128; this.child[i][j]["vy"]+=this.basewh[i]/160/200*(1+Math.random()/8); this.child[i][j]["x"]+=this.child[i][j]["vx"]; this.child[i][j]["y"]+=this.child[i][j]["vy"]; let rgrd = this.ctx[i].createRadialGradient( this.child[i][j]["x"], this.child[i][j]["y"], r, this.child[i][j]["x"], this.child[i][j]["y"], 0 ); let op=(100-this.flag[i])/100; rgrd.addColorStop(0.0, 'rgba('+this.child[i][j]["c"]+','+0.0*op+')'); rgrd.addColorStop(0.6, 'rgba('+this.child[i][j]["c"]+','+0.8*op+')'); rgrd.addColorStop(1.0, 'rgba('+this.child[i][j]["c"]+','+1.0*op+')'); this.ctx[i].beginPath(); this.ctx[i].arc(this.child[i][j]["x"], this.child[i][j]["y"], r, 0, 2 * Math.PI); this.ctx[i].fillStyle = rgrd; this.ctx[i].fill(); } this.flag[i]++; }else{ this.flag[i]++; if(this.flag[i]==0){ this.reset(i); } } } } window.addEventListener("DOMContentLoaded",this.init.bind(this)); setInterval(this.draw.bind(this),20); } MamHanabi=new TMamHanabi(); </script>