Files

29 lines
1.7 KiB
JavaScript

// party popper wobbles, then bangs out confetti and curly streamers that drift down
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=70
const STRIPES=['#4dabf7','#ffd43b','#ff6b6b'],CF=['#ff6b6b','#ffd43b','#4dabf7','#69db7c','#b197fc','#f783ac','#ffa94d']
export default(c,t,i)=>{
const shake=t<.2?(i%2?.06:-.06):0,u=(t-.2)/.7,kick=u>0&&u<.15?-.15*(1-u/.15):0
if(u>0&&u<1){
for(let k=0;k<3;k++){
const a=-PI/4+(k-1)*.45,len=150*min(1,u*2.2),col=CF[k+3]
for(const[w,s]of[[11,'#111'],[5,col]]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();for(let v=0;v<=1;v+=.04){const d=24+len*v,x=88+cos(a)*d-sin(a)*10*sin(v*14),y=168+sin(a)*d+cos(a)*10*sin(v*14)+u*u*60*v;c.lineTo(x,y)}c.stroke()}
}
c.strokeStyle='#111'
for(let k=0;k<14;k++){
const a=-PI/4+((k*.37)%1-.5)*1.4,sp=140+(k*53%60),x=88+cos(a)*sp*u+16,y=168+sin(a)*sp*u+190*u*u-16
if(y>250)continue
c.save();c.translate(x,y);c.rotate(u*T*(1+k%3));c.fillStyle=CF[k%CF.length];c.lineWidth=3;c.beginPath()
if(k%3==0)c.rect(-6,-3.5,12,7);else if(k%3==1)c.arc(0,0,5,0,T);else c.moveTo(0,-6),c.lineTo(6,5),c.lineTo(-6,5),c.closePath()
c.fill();c.stroke();c.restore()
}
}
c.lineWidth=7
c.translate(60,200);c.rotate(shake+kick);c.translate(-60,-200)
const cone=()=>{c.beginPath();c.moveTo(34,230);c.lineTo(72,140);c.lineTo(122,190);c.closePath()}
cone();c.fillStyle='#fff';c.fill()
c.save();cone();c.clip();STRIPES.forEach((col,k)=>{c.strokeStyle=col;c.lineWidth=14;c.beginPath();c.moveTo(20+k*30,250);c.lineTo(110+k*30,140);c.stroke()});c.restore()
cone();c.strokeStyle='#111';c.lineWidth=7;c.stroke()
c.fillStyle='#ffd43b';c.beginPath();c.ellipse(97,165,35,10,PI/4,0,T);c.fill();c.stroke()
}