diff --git a/gen/color/boat/sail.js b/gen/color/boat/sail.js new file mode 100644 index 0000000..2931272 --- /dev/null +++ b/gen/color/boat/sail.js @@ -0,0 +1,21 @@ +// sailboat rocking over rolling waves, its little flag flapping at the top of the mast +const{sin,cos,PI}=Math,T=2*PI +export const frames=20,delay=80 +const HULL='#ff922b',HD='#e8590c',SAIL='#fff',STR='#4dabf7',FL='#ff6b6b',W1='#74c0fc',W2='#4dabf7' +export default(c,t)=>{ + const r=.1*sin(t*T),b=5*sin(t*T+1) + const wave=(base,amp,ph,col)=>{c.fillStyle=col;c.beginPath();c.moveTo(22,246);c.quadraticCurveTo(8,246,8,232);for(let x=8;x<=248;x+=4)c.lineTo(x,base+amp*sin(x/26-t*T+ph));c.lineTo(248,232);c.quadraticCurveTo(248,246,234,246);c.closePath();c.fill();c.stroke()} + wave(196,6,1.5,W1) + c.save();c.translate(128,196+b);c.rotate(r);c.translate(-128,-196) + c.lineWidth=7 + c.beginPath();c.moveTo(128,190);c.lineTo(128,34);c.lineWidth=8;c.stroke();c.lineWidth=7 + c.fillStyle=FL;c.beginPath();c.moveTo(128,34);for(let k=0;k<=10;k++)c.lineTo(128+k*3.4,36+k*.4+4*sin(k*.7-t*T*2)*k/10);for(let k=10;k>=0;k--)c.lineTo(128+k*3.4,56-k*1+4*sin(k*.7-t*T*2)*k/10);c.closePath();c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7 + c.fillStyle=SAIL;c.beginPath();c.moveTo(134,58);c.quadraticCurveTo(196,110,196,170);c.lineTo(134,170);c.closePath();c.fill();c.stroke() + c.save();c.clip();c.fillStyle=STR;c.fillRect(130,120,80,18);c.restore();c.beginPath();c.moveTo(134,58);c.quadraticCurveTo(196,110,196,170);c.lineTo(134,170);c.closePath();c.stroke() + c.beginPath();c.moveTo(122,72);c.quadraticCurveTo(78,120,74,168);c.lineTo(122,168);c.closePath();c.fill();c.stroke() + c.fillStyle=HULL;c.beginPath();c.moveTo(46,176);c.lineTo(214,176);c.quadraticCurveTo(204,214,182,214);c.lineTo(78,214);c.quadraticCurveTo(58,214,46,176);c.fill();c.stroke() + c.fillStyle=HD;c.beginPath();c.rect(56,186,150,8);c.fill() + c.fillStyle='#fff';c.lineWidth=4;for(const x of[96,128,160])c.beginPath(),c.arc(x,200,6,0,T),c.fill(),c.stroke() + c.restore();c.lineWidth=7 + wave(214,5,0,W2) +} diff --git a/gen/color/car/drive.js b/gen/color/car/drive.js new file mode 100644 index 0000000..28d154c --- /dev/null +++ b/gen/color/car/drive.js @@ -0,0 +1,28 @@ +// little car driving along, bouncing on its springs, wheels spinning, road dashes and exhaust puffs rolling past +const{sin,cos,PI,abs}=Math,T=2*PI +export const frames=16,delay=60 +const BODY='#ff6b6b',WIN='#a5d8ff',TIRE='#343a40',HUB='#ced4da',LIGHT='#ffd43b',SMK='#dee2e6',BL='#ffa8a8' +export default(c,t)=>{ + const b=-3*abs(sin(2*T*t)),rot=-t*T/2 + c.fillStyle='#868e96';c.beginPath();c.roundRect(4,214,248,22,11);c.fill();c.stroke() + c.save();c.beginPath();c.rect(10,214,236,22);c.clip() + for(let k=-1;k<5;k++){const x=k*64-((t*128)%64)+20;c.fillStyle='#fff';c.beginPath();c.roundRect(x,222,30,6,3);c.fill()} + c.restore() + for(let k=0;k<3;k++){const p=(t+k/3)%1;c.fillStyle=SMK;c.lineWidth=5;c.beginPath();c.arc(40-p*36,176-p*30,6+p*12,0,T);c.fill();c.stroke()} + c.lineWidth=7 + c.translate(0,b) + c.fillStyle=BODY;c.beginPath();c.moveTo(48,190);c.lineTo(48,150);c.quadraticCurveTo(50,132,72,128);c.lineTo(94,96);c.quadraticCurveTo(100,86,114,86);c.lineTo(164,86);c.quadraticCurveTo(178,86,186,98);c.lineTo(204,128);c.quadraticCurveTo(222,132,224,150);c.lineTo(224,190);c.closePath();c.fill();c.stroke() + c.fillStyle=WIN;c.beginPath();c.moveTo(102,124);c.lineTo(116,100);c.lineTo(132,100);c.lineTo(132,124);c.closePath();c.fill();c.lineWidth=5;c.stroke() + c.beginPath();c.moveTo(144,124);c.lineTo(144,100);c.lineTo(166,100);c.lineTo(184,124);c.closePath();c.fill();c.stroke() + c.fillStyle='#fff';c.beginPath();c.ellipse(118,110,4,8,.4,0,T);c.fill() + c.fillStyle=LIGHT;c.beginPath();c.roundRect(212,144,14,14,4);c.fill();c.stroke() + c.lineWidth=4;c.beginPath();c.moveTo(138,134);c.lineTo(138,180);c.stroke();c.beginPath();c.moveTo(150,148);c.lineTo(162,148);c.stroke() + c.fillStyle='#111';c.beginPath();c.arc(198,170,4,0,T);c.fill() + c.lineWidth=4;c.beginPath();c.arc(206,172,6,.2*PI,.8*PI);c.stroke() + c.translate(0,-b) + for(const x of[88,184]){ + c.lineWidth=7;c.fillStyle=TIRE;c.beginPath();c.arc(x,196,24,0,T);c.fill();c.stroke() + c.fillStyle=HUB;c.beginPath();c.arc(x,196,11,0,T);c.fill();c.lineWidth=4;c.stroke() + for(let k=0;k<4;k++){const a=rot+k*PI/2;c.beginPath();c.moveTo(x+cos(a)*4,196+sin(a)*4);c.lineTo(x+cos(a)*10,196+sin(a)*10);c.stroke()} + } +} diff --git a/gen/color/coin/spin.js b/gen/color/coin/spin.js new file mode 100644 index 0000000..5c0b98f --- /dev/null +++ b/gen/color/coin/spin.js @@ -0,0 +1,22 @@ +// gold coin spinning on the spot, star on one face and a heart on the other, glints popping off it +const{sin,cos,PI,abs,max}=Math,T=2*PI +export const frames=24,delay=50 +const G='#ffd43b',GD='#f59f00',GE='#fab005' +export default(c,t)=>{ + const a=t*T,k=cos(a),w=max(4,72*abs(k)),y=-6*sin(2*T*t),edge=10*sin(a) + for(const[x,yy,o]of[[44,60,0],[210,70,.5],[200,196,.25]]){const s=10*max(0,sin(PI*((t*2+o)%1)));if(s>1.5){c.lineWidth=4;c.fillStyle='#fff';c.beginPath();c.moveTo(x,yy-s);for(const[px,py,qx,qy]of[[s,0,s*.18,-s*.18],[0,s,s*.18,s*.18],[-s,0,-s*.18,s*.18],[0,-s,-s*.18,-s*.18]])c.quadraticCurveTo(x+qx,yy+qy,x+px,yy+py);c.fill();c.stroke()}} + c.lineWidth=7;c.translate(128,128+y) + c.fillStyle=GE;c.beginPath();c.ellipse(edge,0,w,72,0,0,T);c.fill();c.stroke() + c.beginPath();c.rect(Math.min(0,edge),-72,abs(edge),144);c.fill() + c.fillStyle=G;c.beginPath();c.ellipse(0,0,w,72,0,0,T);c.fill();c.stroke() + if(w>14){ + c.save();c.scale(w/72,1) + c.lineWidth=5/(w/72);c.beginPath();c.arc(0,0,56,0,T);c.strokeStyle=GD;c.stroke();c.strokeStyle='#111' + c.fillStyle=GD;c.beginPath() + if(k>0)for(let j=0;j<10;j++){const r=j%2?14:32,b=j*PI/5-PI/2;c.lineTo(cos(b)*r,sin(b)*r)} + else c.moveTo(0,22),c.bezierCurveTo(-34,0,-22,-30,0,-14),c.bezierCurveTo(22,-30,34,0,0,22) + c.closePath();c.fill();c.lineWidth=4/(w/72);c.stroke() + c.restore() + c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.ellipse(0,0,w*.78,56,0,PI*1.15,PI*1.38);c.stroke();c.strokeStyle='#111' + } +} diff --git a/gen/color/fireworks/burst.js b/gen/color/fireworks/burst.js new file mode 100644 index 0000000..3aabc35 --- /dev/null +++ b/gen/color/fireworks/burst.js @@ -0,0 +1,21 @@ +// fireworks shooting up and bursting into colored sparks, one after another +const{sin,cos,PI,min}=Math,T=2*PI +export const frames=24,delay=70 +const F=[[80,70,'#ff6b6b',0,52],[180,90,'#4dabf7',.33,46],[128,52,'#ffd43b',.66,58]] +export default(c,t)=>{ + for(const[x,y,col,o,R]of F){ + const p=(t+o)%1 + if(p<.28){ + const q=p/.28,yy=250-(250-y)*(1-(1-q)**2) + for(const[w,s]of[[9,'#111'],[4,col]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x,yy),c.lineTo(x,yy+22),c.stroke() + c.fillStyle='#fff';c.lineWidth=3;c.strokeStyle='#111';c.beginPath();c.arc(x,yy,4,0,T);c.fill();c.stroke() + continue + } + const q=(p-.28)/.72,r=R*(1-(1-q)**2.5),len=min(22,r)*(1-q*.7),fall=q*q*24 + for(let k=0;k<12;k++){ + const a=k*T/12+o*3,x1=x+cos(a)*(r-len),y1=y+sin(a)*(r-len)+fall,x2=x+cos(a)*r,y2=y+sin(a)*r+fall + if(q<.9)for(const[w,s]of[[9,'#111'],[4,col]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x1,y1),c.lineTo(x2,y2),c.stroke() + const ds=4*(1-q)+1;c.fillStyle=k%2?col:'#fff';c.lineWidth=3;c.strokeStyle='#111';c.beginPath();c.arc(x2+cos(a)*6,y2+sin(a)*6+fall*.3,ds,0,T);c.fill();c.stroke() + } + } +} diff --git a/gen/color/gem/shine.js b/gen/color/gem/shine.js new file mode 100644 index 0000000..8ed8367 --- /dev/null +++ b/gen/color/gem/shine.js @@ -0,0 +1,23 @@ +// cut gem bobbing in place, light shimmering across its facets, a glint sweeping over and sparkles popping +const{sin,cos,PI,max}=Math,T=2*PI +export const frames=24,delay=70 +const SH=['#c5f6fa','#99e9f2','#66d9e8','#3bc9db','#22b8cf'] +const TOPL=[[92,72],[164,72]],G=[[44,104],[86,104],[128,104],[170,104],[212,104]],BOT=[128,224] +export default(c,t)=>{ + const y=-5*sin(t*T) + for(const[x,yy,o]of[[40,52,0],[218,64,.33],[214,176,.66],[42,180,.15]]){const s=12*max(0,sin(PI*((t*2+o)%1)));if(s>1.5){c.lineWidth=4;c.fillStyle='#fff';c.beginPath();c.moveTo(x,yy-s);for(const[px,py,qx,qy]of[[s,0,s*.18,-s*.18],[0,s,s*.18,s*.18],[-s,0,-s*.18,s*.18],[0,-s,-s*.18,-s*.18]])c.quadraticCurveTo(x+qx,yy+qy,x+px,yy+py);c.fill();c.stroke()}} + c.translate(0,y) + const sh=k=>SH[((k+Math.floor(t*10))%SH.length+SH.length)%SH.length] + const tri=(a,b,d,k)=>{c.fillStyle=sh(k);c.beginPath();c.moveTo(...a);c.lineTo(...b);c.lineTo(...d);c.closePath();c.fill()} + c.fillStyle=sh(0);c.beginPath();c.moveTo(...TOPL[0]);c.lineTo(...TOPL[1]);c.lineTo(...G[3]);c.lineTo(...G[1]);c.closePath();c.fill() + tri(G[0],TOPL[0],G[1],1);tri(TOPL[1],G[4],G[3],2);tri(TOPL[0],G[1],G[2],3);tri(TOPL[1],G[2],G[3],4) + for(let k=0;k<4;k++)tri(G[k],G[k+1],BOT,k+2) + c.save();c.beginPath();c.moveTo(...G[0]);c.lineTo(...TOPL[0]);c.lineTo(...TOPL[1]);c.lineTo(...G[4]);c.lineTo(...BOT);c.closePath();c.clip() + const g=((t*1.4)%1)*260-60;c.strokeStyle='#fff';c.lineWidth=14;c.beginPath();c.moveTo(g,230);c.lineTo(g+80,40);c.stroke();c.restore() + c.strokeStyle='#111';c.lineWidth=4;c.beginPath() + c.moveTo(...G[0]);c.lineTo(...G[4]) + for(const p of[G[1],G[2],G[3]])c.moveTo(...p),c.lineTo(...BOT) + c.moveTo(...TOPL[0]);c.lineTo(...G[1]);c.lineTo(...TOPL[0]);c.lineTo(...G[2]);c.moveTo(...TOPL[1]);c.lineTo(...G[3]);c.moveTo(...TOPL[1]);c.lineTo(...G[2]) + c.stroke() + c.lineWidth=7;c.beginPath();c.moveTo(...G[0]);c.lineTo(...TOPL[0]);c.lineTo(...TOPL[1]);c.lineTo(...G[4]);c.lineTo(...BOT);c.closePath();c.stroke() +} diff --git a/gen/color/kite/fly.js b/gen/color/kite/fly.js new file mode 100644 index 0000000..8edb906 --- /dev/null +++ b/gen/color/kite/fly.js @@ -0,0 +1,23 @@ +// diamond kite dancing in the wind with its bow tail waving, clouds drifting past +const{sin,cos,PI,atan2}=Math,T=2*PI +export const frames=24,delay=70 +const Q=['#ff6b6b','#ffd43b','#4dabf7','#69db7c'],BOWS=['#f783ac','#b197fc','#ffa94d','#38d9a9'] +const cloud=(c,x,y,s)=>{const P=[[-14*s,2*s,11*s],[0,-6*s,15*s],[14*s,2*s,11*s]],b=()=>c.roundRect(x-26*s,y,52*s,16*s,8*s);c.lineWidth=12;for(const[a,bb,r]of P)c.beginPath(),c.arc(x+a,y+bb,r,0,T),c.stroke();c.beginPath();b();c.stroke();c.fillStyle='#fff';for(const[a,bb,r]of P)c.beginPath(),c.arc(x+a,y+bb,r,0,T),c.fill();c.beginPath();b();c.fill();c.lineWidth=7} +export default(c,t)=>{ + for(const[y,o,s]of[[50,0,1],[190,.5,.8]]){const p=(t+o)%1;cloud(c,290-p*340,y,s)} + const kx=140+18*sin(t*T),ky=86+12*sin(2*T*t),r=.2*sin(t*T+.5) + for(const[w,s]of[[6,'#111'],[2,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(kx,ky+56),c.quadraticCurveTo(70,200,20,246),c.stroke() + c.strokeStyle='#111' + const tail=[];for(let k=0;k<=24;k++){const u=k/24;tail.push([kx-sin(r)*60+u*60+12*sin(u*7-t*T*2),ky+cos(r)*60+u*100])} + for(const[w,s]of[[8,'#111'],[3,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();for(const[x,y]of tail)c.lineTo(x,y);c.stroke()} + c.strokeStyle='#111' + for(let k=1;k<=4;k++){const[x,y]=tail[k*5],[px,py]=tail[k*5-1],a=atan2(y-py,x-px)+PI/2;c.save();c.translate(x,y);c.rotate(a);c.fillStyle=BOWS[k-1];c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.moveTo(0,0),c.lineTo(d*14,-7),c.lineTo(d*14,7),c.closePath(),c.fill(),c.stroke();c.restore()} + c.save();c.translate(kx,ky);c.rotate(r);c.lineWidth=7 + const pts=[[0,-64],[46,-6],[0,62],[-46,-6]],ctr=[0,-6] + for(let k=0;k<4;k++){c.fillStyle=Q[k];c.beginPath();c.moveTo(...ctr);c.lineTo(...pts[k]);c.lineTo(...pts[(k+1)%4]);c.closePath();c.fill()} + c.beginPath();for(const p of pts)c.lineTo(...p);c.closePath();c.stroke() + c.lineWidth=4;c.beginPath();c.moveTo(0,-64);c.lineTo(0,62);c.moveTo(-46,-6);c.lineTo(46,-6);c.stroke() + c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*12,-20,4,0,T),c.fill() + c.lineWidth=4;c.beginPath();c.arc(0,-14,6,.15*PI,.85*PI);c.stroke() + c.restore() +} diff --git a/gen/color/pencil/write.js b/gen/color/pencil/write.js new file mode 100644 index 0000000..f96f686 --- /dev/null +++ b/gen/color/pencil/write.js @@ -0,0 +1,27 @@ +// pencil writing endless cursive loops while the paper slides along under it +const{sin,cos,PI,atan2}=Math,T=2*PI +export const frames=24,delay=60 +const PAPER='#fff9db',RULE='#a5d8ff',INK='#364fc7',Y='#ffd43b',YD='#fab005',WD='#ffd8a8',ER='#faa2c1',FE='#ced4da' +const R=10,D=17,TIP=162 +const pt=th=>[R*th-D*sin(th),-D*cos(th)] +export default(c,t)=>{ + const off=t*2*T*R + c.fillStyle=PAPER;c.beginPath();c.roundRect(16,64,224,140,12);c.fill();c.stroke() + c.strokeStyle=RULE;c.lineWidth=3;for(const y of[96,128,160,192])c.beginPath(),c.moveTo(28,y),c.lineTo(228,y),c.stroke() + c.strokeStyle='#ff8787';c.beginPath();c.moveTo(48,68);c.lineTo(48,200);c.stroke() + c.save();c.beginPath();c.rect(20,64,220,140);c.clip() + c.strokeStyle=INK;c.lineWidth=5;c.beginPath() + let tip=[0,0] + for(let th=(off-TIP)/R-2;th<=(off+TIP)/R;th+=.06){const[x,y]=pt(th),sx=x-off+TIP-pt(0)[0],sy=136+y;if(sx>TIP+.5)break;c.lineTo(sx,sy);tip=[sx,sy]} + c.stroke();c.restore() + c.strokeStyle='#111';c.lineWidth=7 + const[tx,ty]=tip + c.save();c.translate(tx,ty);c.rotate(-PI/3.4) + c.fillStyle=WD;c.beginPath();c.moveTo(0,0);c.lineTo(-12,-28);c.lineTo(12,-28);c.closePath();c.fill();c.stroke() + c.fillStyle='#495057';c.beginPath();c.moveTo(0,0);c.lineTo(-5,-11);c.lineTo(5,-11);c.closePath();c.fill() + c.fillStyle=Y;c.beginPath();c.rect(-13,-130,26,102);c.fill();c.stroke() + c.fillStyle=YD;c.fillRect(4,-127,6,96) + c.fillStyle=FE;c.beginPath();c.rect(-14,-150,28,20);c.fill();c.stroke() + c.fillStyle=ER;c.beginPath();c.roundRect(-13,-172,26,24,[8,8,0,0]);c.fill();c.stroke() + c.restore() +} diff --git a/gen/color/popper/pop.js b/gen/color/popper/pop.js new file mode 100644 index 0000000..cefd174 --- /dev/null +++ b/gen/color/popper/pop.js @@ -0,0 +1,28 @@ +// 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() +} diff --git a/gen/color/potion/bubble.js b/gen/color/potion/bubble.js new file mode 100644 index 0000000..d51dd56 --- /dev/null +++ b/gen/color/potion/bubble.js @@ -0,0 +1,21 @@ +// round potion flask bubbling away, purple liquid sloshing, little puffs of vapor drifting out the top +const{sin,cos,PI}=Math,T=2*PI +export const frames=24,delay=70 +const LQ='#b197fc',LD='#9775fa',GL='#e7f5ff',VP='#e5dbff',LB='#fff9db' +const flask=c=>{c.beginPath();c.moveTo(108,58);c.lineTo(108,104);c.arc(128,164,64,-PI/2-.32,-PI/2+.32,true);c.lineTo(148,104);c.lineTo(148,58);c.closePath()} +export default(c,t)=>{ + for(let k=0;k<3;k++){const p=(t+k/3)%1;c.fillStyle=VP;c.lineWidth=5;c.beginPath();c.arc(128+14*sin(p*T+k*2)+(k-1)*8,46-p*44,8+10*p,0,T);c.fill();c.stroke()} + c.lineWidth=7 + flask(c);c.fillStyle=GL;c.fill() + c.save();flask(c);c.clip() + const lv=x=>132+5*sin(x/18-t*T*2) + c.fillStyle=LQ;c.beginPath();c.moveTo(40,250);for(let x=40;x<=216;x+=4)c.lineTo(x,lv(x));c.lineTo(216,250);c.fill();c.lineWidth=5;c.stroke() + c.fillStyle=LD;c.beginPath();c.ellipse(150,200,40,22,-.3,0,T);c.fill() + c.fillStyle='#fff';c.lineWidth=4 + for(const[x0,o,r]of[[104,0,7],[140,.3,5],[124,.6,9],[160,.8,6],[92,.45,4]]){const p=(t*1.5+o)%1,y=212-p*(212-lv(x0)),s=r*(p<.9?1:(1-p)*10);if(s>.5)c.beginPath(),c.arc(x0+4*sin(p*T*2+o*9),y,s,0,T),c.fill(),c.stroke()} + c.restore();c.lineWidth=7;flask(c);c.stroke() + c.fillStyle=LB;c.beginPath();c.roundRect(102,144,52,40,6);c.fill();c.lineWidth=5;c.stroke() + c.fillStyle='#ff6b6b';c.beginPath();c.moveTo(128,176);c.bezierCurveTo(112,166,116,152,128,160);c.bezierCurveTo(140,152,144,166,128,176);c.fill();c.lineWidth=4;c.stroke() + c.lineWidth=7;c.fillStyle=GL;c.beginPath();c.roundRect(100,52,56,12,6);c.fill();c.stroke() + c.strokeStyle='#fff';c.lineWidth=6;c.beginPath();c.arc(128,164,48,PI*1.12,PI*1.38);c.stroke() +} diff --git a/gen/color/umbrella/twirl.js b/gen/color/umbrella/twirl.js new file mode 100644 index 0000000..67ea1ca --- /dev/null +++ b/gen/color/umbrella/twirl.js @@ -0,0 +1,32 @@ +// umbrella twirling in the rain, colored panels sweeping round, raindrops splashing off the top +const{sin,cos,PI,asin,max}=Math,T=2*PI +export const frames=24,delay=60 +const COL=['#ff6b6b','#ffd43b','#4dabf7','#ff6b6b','#ffd43b','#4dabf7'],BU='#a5d8ff' +const CX=128,TOP=46,BASE=124,RX=94 +const dome=c=>{c.beginPath();c.moveTo(CX-RX,BASE);c.bezierCurveTo(CX-RX,TOP-20,CX+RX,TOP-20,CX+RX,BASE);const n=6;for(let k=0;k{const u=(x-CX)/RX;return BASE-(BASE-TOP+16)*(1-u*u)*.98} +export default(c,t)=>{ + const rot=t*T/3 + for(const[x,o]of[[60,0],[104,.4],[150,.7],[196,.2],[226,.55]]){ + const p=(t*2+o)%1,ys=surf(x)-6,y=-20+p*(ys+20)*1.6 + c.lineWidth=4;c.fillStyle=BU + if(yPI)continue;const x=CX+RX*cos(a);c.beginPath();c.moveTo(CX,TOP-6);c.quadraticCurveTo(x,TOP,x,BASE+4);c.stroke()} + c.restore();c.lineWidth=7;dome(c);c.stroke() + c.fillStyle='#ced4da';c.beginPath();c.roundRect(CX-4,TOP-24,8,16,4);c.fill();c.lineWidth=5;c.stroke() +} diff --git a/public/boat/sail.gif b/public/boat/sail.gif new file mode 100644 index 0000000..7ebe29e Binary files /dev/null and b/public/boat/sail.gif differ diff --git a/public/boat/sail.webp b/public/boat/sail.webp new file mode 100644 index 0000000..5278cdb Binary files /dev/null and b/public/boat/sail.webp differ diff --git a/public/car/drive.gif b/public/car/drive.gif new file mode 100644 index 0000000..6e2e444 Binary files /dev/null and b/public/car/drive.gif differ diff --git a/public/car/drive.webp b/public/car/drive.webp new file mode 100644 index 0000000..a1663e0 Binary files /dev/null and b/public/car/drive.webp differ diff --git a/public/coin/spin.gif b/public/coin/spin.gif new file mode 100644 index 0000000..07fc34d Binary files /dev/null and b/public/coin/spin.gif differ diff --git a/public/coin/spin.webp b/public/coin/spin.webp new file mode 100644 index 0000000..6672d1b Binary files /dev/null and b/public/coin/spin.webp differ diff --git a/public/fireworks/burst.gif b/public/fireworks/burst.gif new file mode 100644 index 0000000..e475141 Binary files /dev/null and b/public/fireworks/burst.gif differ diff --git a/public/fireworks/burst.webp b/public/fireworks/burst.webp new file mode 100644 index 0000000..049971c Binary files /dev/null and b/public/fireworks/burst.webp differ diff --git a/public/gem/shine.gif b/public/gem/shine.gif new file mode 100644 index 0000000..20034e8 Binary files /dev/null and b/public/gem/shine.gif differ diff --git a/public/gem/shine.webp b/public/gem/shine.webp new file mode 100644 index 0000000..68e94d3 Binary files /dev/null and b/public/gem/shine.webp differ diff --git a/public/kite/fly.gif b/public/kite/fly.gif new file mode 100644 index 0000000..75fca09 Binary files /dev/null and b/public/kite/fly.gif differ diff --git a/public/kite/fly.webp b/public/kite/fly.webp new file mode 100644 index 0000000..a7b38bd Binary files /dev/null and b/public/kite/fly.webp differ diff --git a/public/pencil/write.gif b/public/pencil/write.gif new file mode 100644 index 0000000..db004c8 Binary files /dev/null and b/public/pencil/write.gif differ diff --git a/public/pencil/write.webp b/public/pencil/write.webp new file mode 100644 index 0000000..e996e7c Binary files /dev/null and b/public/pencil/write.webp differ diff --git a/public/popper/pop.gif b/public/popper/pop.gif new file mode 100644 index 0000000..fbd5f83 Binary files /dev/null and b/public/popper/pop.gif differ diff --git a/public/popper/pop.webp b/public/popper/pop.webp new file mode 100644 index 0000000..6aaa8b6 Binary files /dev/null and b/public/popper/pop.webp differ diff --git a/public/potion/bubble.gif b/public/potion/bubble.gif new file mode 100644 index 0000000..10984a1 Binary files /dev/null and b/public/potion/bubble.gif differ diff --git a/public/potion/bubble.webp b/public/potion/bubble.webp new file mode 100644 index 0000000..1d6cd72 Binary files /dev/null and b/public/potion/bubble.webp differ diff --git a/public/umbrella/twirl.gif b/public/umbrella/twirl.gif new file mode 100644 index 0000000..e0ea480 Binary files /dev/null and b/public/umbrella/twirl.gif differ diff --git a/public/umbrella/twirl.webp b/public/umbrella/twirl.webp new file mode 100644 index 0000000..555e955 Binary files /dev/null and b/public/umbrella/twirl.webp differ