Add 50 original memes as a pending section on /test
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@@ -0,0 +1,50 @@
|
|||||||
|
// a posh egg gentleman gasps, his monocle pops out and swings on its chain, top hat hops off his head: THE AUDACITY!
|
||||||
|
const{sin,cos,PI,min,max,exp,atan2,hypot}=Math,T=2*PI
|
||||||
|
export const frames=26,delay=95,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)},pop=u=>(u=cl(u),u<.6?1.25*u/.6:1.25-.25*(u-.6)/.4)
|
||||||
|
const G={T:'0080 404c',H:'000c 808c 0686',E:'80000c8c 0666'," ":'',A:'0c0440848c 0787',U:'000a2c6c8a80',D:'005083895c0c00',C:'826020020a2c6c8a',I:'0040 202c 0c4c',Y:'004680 464c',"!":'0008 0c0c'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const CX=128,CY=138,EX=20,EY=-14,AX=46,AY=22,L=hypot(EX-AX,EY-AY),A0=atan2(EX-AX,EY-AY)
|
||||||
|
const egg=c=>{c.beginPath();c.moveTo(0,-72);c.bezierCurveTo(40,-72,58,-10,54,16);c.bezierCurveTo(50,46,28,58,0,58);c.bezierCurveTo(-28,58,-50,46,-54,16);c.bezierCurveTo(-58,-10,-40,-72,0,-72);c.closePath()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const sh=ez(t,.2,.26)*(1-ez(t,.8,.92)),take=pop((t-.22)/.08),sq=t>.22&&t<.32?.1*sin(PI*(t-.22)/.1):0
|
||||||
|
// monocle pendulum angle: sits on the eye at A0, drops and swings, then gets put back
|
||||||
|
const tau=cl(t-.26),sw=t<.26?A0:A0*cos(tau*T*3.2)*exp(-4*tau),back=ez(t,.82,.94),th=sw+(A0-sw)*back
|
||||||
|
const hop=t>.25&&t<.5?sin(PI*(t-.25)/.25):0
|
||||||
|
c.save();c.translate(CX,CY+58);c.scale(1+sq*.6,1-sq);c.translate(0,-58)
|
||||||
|
// bow tie
|
||||||
|
c.fillStyle='#e03131';c.lineWidth=5;c.beginPath();c.moveTo(0,48);c.lineTo(-22,38);c.lineTo(-22,60);c.closePath();c.moveTo(0,48);c.lineTo(22,38);c.lineTo(22,60);c.closePath();c.fill();c.stroke();c.beginPath();c.arc(0,48,6,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff3dc';c.lineWidth=7;egg(c);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ffc9c9';for(const d of[-1,1])c.beginPath(),c.ellipse(d*34,12,9,5,0,0,T),c.fill()
|
||||||
|
// eyes and brows
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
if(sh>.5){c.fillStyle='#fff';c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.arc(d*EX,EY,11,0,T),c.fill(),c.stroke();c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*EX,EY,3.5,0,T),c.fill()
|
||||||
|
c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.moveTo(d*10,-42),c.quadraticCurveTo(d*20,-50,d*32,-42),c.stroke()}
|
||||||
|
else{c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(d*EX,EY,4.5,5.5,0,0,T),c.fill()
|
||||||
|
c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.moveTo(d*EX-8,EY-3),c.lineTo(d*EX+8,EY-3),c.stroke()
|
||||||
|
c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.moveTo(d*10,-28),c.quadraticCurveTo(d*20,-33,d*30,-27),c.stroke()}
|
||||||
|
// mouth under the moustache
|
||||||
|
if(sh>.5){c.fillStyle='#862e2e';c.lineWidth=4;c.beginPath();c.ellipse(0,30,9*take,12*take,0,0,T);c.fill();c.stroke()}
|
||||||
|
else{c.lineWidth=3.5;c.beginPath();c.moveTo(-6,28);c.quadraticCurveTo(0,30,6,28);c.stroke()}
|
||||||
|
// handlebar moustache
|
||||||
|
c.fillStyle='#3b2a1e';c.lineWidth=3;const tw=sh>.5?.1*((i>>2)%2):0
|
||||||
|
for(const d of[-1,1]){c.save();c.scale(d,1);c.rotate(tw*d);c.beginPath();c.moveTo(0,10);c.bezierCurveTo(10,4,22,8,28,16);c.bezierCurveTo(34,22,42,16,40,8);c.bezierCurveTo(44,12,44,22,34,25);c.bezierCurveTo(24,28,14,18,0,22);c.closePath();c.fill();c.stroke();c.restore()}
|
||||||
|
// monocle on its chain
|
||||||
|
const mx=AX+L*sin(th),my=AY+L*cos(th),ms=1+.35*take*(1-back)*(t<.4?1:0)
|
||||||
|
c.lineWidth=5;c.strokeStyle='#111';c.beginPath();c.moveTo(AX,AY);c.quadraticCurveTo((AX+mx)/2+4,(AY+my)/2+10*(1-sh),mx,my);c.stroke()
|
||||||
|
c.lineWidth=2.5;c.strokeStyle='#fcc419';c.setLineDash([3,3]);c.stroke();c.setLineDash([])
|
||||||
|
c.fillStyle='#fcc419';c.strokeStyle='#111';c.lineWidth=3;c.beginPath();c.arc(AX,AY,3.5,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.translate(mx,my);c.scale(ms,ms);c.lineWidth=9;c.beginPath();c.arc(0,0,14,0,T);c.stroke();c.lineWidth=5;c.strokeStyle='#fcc419';c.stroke()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=2.5;c.beginPath();c.arc(0,0,8,PI*1.1,PI*1.45);c.stroke();c.restore()
|
||||||
|
c.restore()
|
||||||
|
// top hat hopping off and landing back
|
||||||
|
c.save();c.translate(CX-2,CY-66-18*hop-6*sq);c.rotate(-.1+.5*hop*(t<.375?1:-1)*sin(PI*hop))
|
||||||
|
c.fillStyle='#212529';c.lineWidth=6;c.strokeStyle='#111'
|
||||||
|
c.beginPath();c.moveTo(-29,0);c.lineTo(-32,-50);c.quadraticCurveTo(0,-58,32,-50);c.lineTo(29,0);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#c92a2a';c.beginPath();c.moveTo(-29.5,-6);c.lineTo(-30.5,-18);c.quadraticCurveTo(0,-23,30.5,-18);c.lineTo(29.5,-6);c.quadraticCurveTo(0,-10,-29.5,-6);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#212529';c.beginPath();c.ellipse(0,0,46,9,0,0,T);c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#495057';c.lineWidth=3;c.beginPath();c.moveTo(-22,-44);c.lineTo(-22,-26);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
if(sh>.05){const s=min(1.1,pop((t-.24)/.1))*(1-ez(t,.86,.92));c.save();c.translate(128,234);c.scale(s,s);txt(c,'THE AUDACITY!',0,0,17,'#fff');c.restore()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
// squeaky toy mallet comes down BONK on a smiling blob, it squashes flat with spiral eyes and stars circling, then springs back up none the wiser
|
||||||
|
const{sin,cos,PI,max,min}=Math,T=2*PI
|
||||||
|
export const frames=20,delay=84,rim=5
|
||||||
|
const Y='#ffd43b',BL='#ff8787',HR='#fa5252',HB='#ffd43b',HD='#4dabf7'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const G={B:[[0,3,0,0,2.6,0,3.6,.8,3.6,2.2,2.6,3,0,3],[0,3,0,6,2.8,6,4,5,4,4,2.8,3,0,3]],O:[[2,0,3.4,.6,4,2,4,4,3.4,5.4,2,6,.6,5.4,0,4,0,2,.6,.6,2,0]],N:[[0,6,0,0,4,6,4,0]],K:[[0,0,0,6],[3.8,0,0,3.8],[1.5,2.3,4,6]],'!':[[0,0,0,3.6],[0,6,0,6]]}
|
||||||
|
const word=(c,s,h,col)=>{
|
||||||
|
const k=h/6,adv=s.split('').map(ch=>ch=='!'?1.8:6),W=(adv.reduce((a,b)=>a+b)-2)*k
|
||||||
|
for(const[w,st]of[[h*.52,'#111'],[h*.26,col]]){c.lineWidth=w;c.strokeStyle=st;let x=-W/2;c.beginPath()
|
||||||
|
s.split('').forEach((ch,j)=>{for(const p of G[ch]){c.moveTo(x+p[0]*k,p[1]*k-h/2);for(let q=2;q<p.length;q+=2)c.lineTo(x+p[q]*k,p[q+1]*k-h/2)}x+=adv[j]*k})
|
||||||
|
c.stroke()}
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
}
|
||||||
|
const star=(c,x,y,s,a)=>{c.save();c.translate(x,y);c.rotate(a);c.fillStyle=Y;c.lineWidth=4;c.beginPath();for(let k=0;k<10;k++){const r=k%2?s*.45:s,b=k*PI/5-PI/2;c.lineTo(cos(b)*r,sin(b)*r)}c.closePath();c.fill();c.stroke();c.restore()}
|
||||||
|
const spiral=(c,x,y,a)=>{c.lineWidth=4;c.beginPath();for(let b=0;b<4*PI;b+=.3){const r=1+b*1.05;c.lineTo(x+cos(b+a)*r,y+sin(b+a)*r)}c.stroke()}
|
||||||
|
export default(c,t)=>{
|
||||||
|
// swing: raised, wind-up wobble, slam at .3, lift back by .7
|
||||||
|
const down=ez(t,.24,.3),up=ez(t,.42,.72),hit=t>=.3&&t<.42
|
||||||
|
const sq=t<.3?0:t<.42?1:max(0,1-ez(t,.42,.52)*1.25)+(t>.42&&t<.7?sin((t-.42)*T*3.5)*.18*(1-ez(t,.42,.7)):0)
|
||||||
|
const sy=1-.48*sq,sx=1+.4*sq
|
||||||
|
const dz=t>=.36&&t<.92,fz=1-ez(t,.82,.92)
|
||||||
|
// blob
|
||||||
|
c.save();c.translate(116,236);c.scale(sx,sy)
|
||||||
|
c.fillStyle=Y;c.beginPath();c.moveTo(-70,0);c.bezierCurveTo(-74,-70,-48,-118,0,-118);c.bezierCurveTo(48,-118,74,-70,70,0);c.closePath();c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
const fy=236-60*sy,ex=27*sx
|
||||||
|
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(116+d*(ex+16),fy+14*sy,10,5,0,0,T),c.fill()
|
||||||
|
c.fillStyle='#111'
|
||||||
|
if(hit){c.lineWidth=5;for(const d of[-1,1]){const x=116+d*ex,y=fy;c.beginPath();c.moveTo(x-8,y-6);c.lineTo(x+8,y+6);c.moveTo(x+8,y-6);c.lineTo(x-8,y+6);c.stroke()}
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(100,fy+20);c.lineTo(132,fy+20);c.stroke()}
|
||||||
|
else if(dz){for(const d of[-1,1])spiral(c,116+d*ex,fy-2,t*T*4*d)
|
||||||
|
c.lineWidth=4.5;c.beginPath();for(let x=-16;x<=16;x+=2)c.lineTo(116+x,fy+20+3*sin(x/4+t*T*3));c.stroke()}
|
||||||
|
else{const look=t<.3?ez(t,.12,.2)*-5:0
|
||||||
|
for(const d of[-1,1])c.beginPath(),c.ellipse(116+d*ex,fy-2+look,6,8,0,0,T),c.fill()
|
||||||
|
c.lineWidth=4.5;c.beginPath();c.arc(116,fy+10,12,.2*PI,.8*PI);c.stroke()}
|
||||||
|
// circling stars
|
||||||
|
if(dz&&!hit&&fz>.4)for(let k=0;k<3;k++){const a=t*T*3+k*T/3,z=sin(a);star(c,116+cos(a)*54,fy-46-z*8+10*(1-sy),(10+3*z)*fz,a)}
|
||||||
|
// mallet: head pose (x,y,handle angle) eases from cocked back up top to flat on the head
|
||||||
|
const top=236-118*sy,w=t<.24?.04*sin(t*T*4):0,k=t<.3?down:1-up
|
||||||
|
const hx=156+(116-156)*k,hy=54+w*60+(top-34-54)*k,ha=-.75+w+(.6)*k
|
||||||
|
c.save();c.translate(hx,hy);c.rotate(ha)
|
||||||
|
c.lineWidth=7;c.fillStyle=HD;c.beginPath();c.roundRect(20,-9,220,18,9);c.fill();c.stroke()
|
||||||
|
if(hit)c.scale(1.12,.86)
|
||||||
|
c.fillStyle=HR;c.beginPath();c.roundRect(-26,-38,52,76,10);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HB;for(const y of[-38,24])c.beginPath(),c.roundRect(-28,y,56,14,7),c.fill(),c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.roundRect(-18,-18,7,30,3.5);c.fill()
|
||||||
|
c.restore()
|
||||||
|
// impact
|
||||||
|
if(hit){const p=ez(t,.3,.34)
|
||||||
|
c.save();c.translate(122,236-120*sy);c.lineWidth=6
|
||||||
|
for(let k=0;k<7;k++){const a=-PI*.95+k*PI*.9/6;for(const[w,s]of[[11,'#111'],[5,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(cos(a)*76,sin(a)*40),c.lineTo(cos(a)*(96+8*p),sin(a)*(54+6*p)),c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
c.save();c.translate(108,46);c.rotate(-.14);const s=1.15-.15*p;c.scale(s,s);word(c,'BONK!',38,'#fff');c.restore()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// side profile of a blank-staring head shown in cross-section, and up top there's nothing but empty desert with a tumbleweed bouncing through on the wind
|
||||||
|
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=Array(24).fill(70),rim=4
|
||||||
|
const SK='#ffd8b5',SKD='#e8a27a',SKY='#fff1d0',SAND='#f2c879',SD='#cf9440',TW='#a5692c',CA='#69db7c',FL=118
|
||||||
|
const head=c=>{c.beginPath();c.moveTo(84,256);c.lineTo(86,206);c.bezierCurveTo(36,186,22,104,52,62);c.bezierCurveTo(86,14,176,12,202,64);c.bezierCurveTo(214,90,214,112,208,128);c.lineTo(228,158);c.quadraticCurveTo(224,164,210,166);c.quadraticCurveTo(216,174,211,180);c.quadraticCurveTo(217,188,209,194);c.quadraticCurveTo(208,210,194,214);c.quadraticCurveTo(178,220,162,218);c.lineTo(160,256)}
|
||||||
|
export default(c,t)=>{
|
||||||
|
c.fillStyle=SK;head(c);c.fill()
|
||||||
|
c.save();head(c);c.clip()
|
||||||
|
// inside the skull: sky, sun, dunes, cactus
|
||||||
|
c.fillStyle=SKY;c.fillRect(0,0,256,FL)
|
||||||
|
c.fillStyle='#ffe066';c.lineWidth=4;c.beginPath();c.arc(168,58,13,0,T);c.fill()
|
||||||
|
c.fillStyle=SAND;c.beginPath();c.moveTo(0,104);c.quadraticCurveTo(70,88,120,100);c.quadraticCurveTo(170,110,256,94);c.lineTo(256,FL);c.lineTo(0,FL);c.fill();c.stroke()
|
||||||
|
c.lineWidth=3;c.strokeStyle=SD;for(const[x,y]of[[70,108],[132,110],[176,104]])c.beginPath(),c.moveTo(x,y),c.lineTo(x+10,y),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.fillStyle=CA;c.lineWidth=4;c.beginPath();c.roundRect(64,64,11,34,5.5);c.fill();c.stroke()
|
||||||
|
for(const[a,b,d]of[[64,82,-1],[75,76,1]])c.beginPath(),c.moveTo(a,b),c.quadraticCurveTo(a+d*10,b,a+d*10,b-10),c.stroke()
|
||||||
|
// wind streaks
|
||||||
|
c.lineWidth=3;c.globalAlpha=.55;for(let k=0;k<4;k++){const x=((t+k*.31)%1)*220+10,y=44+k*14;c.beginPath();c.moveTo(x,y);c.lineTo(x+18+k*5,y);c.stroke()}c.globalAlpha=1
|
||||||
|
// tumbleweed, comes in from behind the skull wall and leaves through the forehead so the loop jump is hidden
|
||||||
|
const x=22+t*204,h=abs(sin(2*T*t)),r=20,y=FL-6-r-h*28,a=x/r*.9
|
||||||
|
c.fillStyle=SD;c.globalAlpha=.45;c.beginPath();c.ellipse(x,FL-5,r*(1-h*.5),3,0,0,T);c.fill();c.globalAlpha=1
|
||||||
|
c.save();c.translate(x,y);c.rotate(a);c.fillStyle='#ecd09a';c.beginPath();c.arc(0,0,r-2,0,T);c.fill();c.strokeStyle=TW;c.lineWidth=4
|
||||||
|
for(let k=0;k<6;k++){c.beginPath();c.ellipse(sin(k*2.1)*3,cos(k*1.7)*3,r-3,(r-3)*(.3+.13*(k%3)),k*PI/6,0,T);c.stroke()}
|
||||||
|
c.strokeStyle='#5c3a17';c.lineWidth=2.5;for(let k=0;k<5;k++){const b=k*1.26;c.beginPath();c.moveTo(cos(b)*r,sin(b)*r);c.lineTo(cos(b)*(r+4),sin(b)*(r+4));c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
// skull wall: thick skin band hugging the outline, with the cut floor
|
||||||
|
for(const[w,s]of[[30,'#111'],[24,SKD],[14,SK]])c.lineWidth=w,c.strokeStyle=s,head(c),c.stroke()
|
||||||
|
c.fillStyle=SK;c.fillRect(0,FL,256,140);c.fillStyle=SKD;c.fillRect(0,FL,256,5);c.lineWidth=3.5;c.strokeStyle='#111';c.beginPath();c.moveTo(0,FL);c.lineTo(256,FL);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
c.lineWidth=7;head(c);c.stroke()
|
||||||
|
// ear, blank stare, flat mouth
|
||||||
|
c.fillStyle=SK;c.lineWidth=6;c.beginPath();c.ellipse(106,176,13,18,.15,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();c.arc(108,176,6,-1.6,1.4);c.stroke()
|
||||||
|
const bl=t>.82&&t<.88
|
||||||
|
c.fillStyle='#111';if(bl){c.beginPath();c.moveTo(182,140);c.lineTo(196,140);c.stroke()}else{c.beginPath();c.arc(190,140,5.5,0,T);c.fill()}
|
||||||
|
c.beginPath();c.moveTo(178,131);c.lineTo(200,132);c.stroke()
|
||||||
|
c.beginPath();c.moveTo(198,187);c.lineTo(210,187);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// two hands creak open a wallet: empty slots, a cobweb, and a moth flutters out in a puff of dust before it snaps shut again
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=32,delay=80,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),lp=(a,b,u)=>a+(b-a)*u
|
||||||
|
const BG='#e5dbff',LE='#a0522d',LD='#7a3b1c',LI='#c8794a',IN='#5e2e14',SKIN='#ffd3b0',SL='#748ffc'
|
||||||
|
const Y0=90,H=96,W=100
|
||||||
|
const moth=(c,x,y,f,a)=>{c.save();c.translate(x,y);c.rotate(a);c.strokeStyle='#111';c.lineWidth=3.5
|
||||||
|
for(const d of[-1,1]){c.save();c.scale(d,f);c.fillStyle='#e6d5b8';c.beginPath();c.moveTo(0,-2);c.quadraticCurveTo(14,-20,22,-8);c.quadraticCurveTo(18,0,0,2);c.fill();c.stroke();c.fillStyle='#c9ad85';c.beginPath();c.moveTo(0,2);c.quadraticCurveTo(14,4,14,12);c.quadraticCurveTo(6,14,0,4);c.fill();c.stroke();c.fillStyle='#8d6e4a';c.beginPath();c.arc(13,-8,2.5,0,T);c.fill();c.restore()}
|
||||||
|
c.fillStyle='#a1845c';c.beginPath();c.ellipse(0,2,4.5,9,0,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=2.5;c.beginPath();for(const d of[-1,1])c.moveTo(0,-6),c.quadraticCurveTo(d*3,-14,d*8,-15);c.stroke();c.restore()}
|
||||||
|
const hand=(c,x,y,d)=>{
|
||||||
|
for(const[w,s]of[[34,'#111'],[24,SL]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x+d*14,262),c.lineTo(x+d*6,y+50),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=SKIN;c.beginPath();c.ellipse(x,y+30,20,26,d*.2,0,T);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.ellipse(x-d*6,y,9,20,-d*.25,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=3;c.beginPath();c.moveTo(x-d*9,y-12);c.lineTo(x-d*3,y-12);c.stroke()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const o=io((t-.1)/.18)-io((t-.86)/.1),th=PI*o,sx=lp(78,128,o),cw=W*cos(th),sh=t>.74&&t<.86?1.5*sin(i*3):0,sy=sh
|
||||||
|
const m=cl((t-.26)/.6),dust=cl((t-.24)/.2)
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=BG;c.fill();c.clip()
|
||||||
|
c.save();c.translate(0,sy)
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=LE;c.beginPath();c.roundRect(sx,Y0,W,H,[0,10,10,0]);c.fill();c.stroke()
|
||||||
|
if(o>.5){
|
||||||
|
c.fillStyle=LI;c.beginPath();c.roundRect(sx+6,Y0+6,W-12,H-12,6);c.fill()
|
||||||
|
c.fillStyle=IN;c.beginPath();c.roundRect(sx+10,Y0+18,W-20,10,4);c.fill()
|
||||||
|
c.strokeStyle=LD;c.lineWidth=3;c.setLineDash([5,5]);c.beginPath();c.roundRect(sx+6,Y0+6,W-12,H-12,6);c.stroke();c.setLineDash([])
|
||||||
|
c.strokeStyle='#f1f3f5';c.lineWidth=2.2;const cx=sx+W-8,cy=Y0+8;c.beginPath();for(let k=0;k<5;k++){const a=PI/2+k*PI/8;c.moveTo(cx,cy);c.lineTo(cx+46*cos(a+PI/2),cy+46*sin(a+PI/2))}for(const r of[14,26,38]){for(let k=0;k<5;k++){const a=PI+k*PI/8;const b=a+PI/8;k?0:c.moveTo(cx+r*cos(a),cy+r*sin(a));if(k<4)c.quadraticCurveTo(cx+r*.8*cos(a+PI/16),cy+r*.8*sin(a+PI/16),cx+r*cos(b),cy+r*sin(b))}}c.stroke()
|
||||||
|
}
|
||||||
|
const L=abs(cw)
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6
|
||||||
|
if(cw>=0){c.fillStyle=LE;c.beginPath();c.roundRect(sx,Y0-2,max(L,2),H+4,[0,10,10,0]);c.fill();c.stroke()
|
||||||
|
if(L>30){c.strokeStyle=LD;c.lineWidth=3;c.setLineDash([5,5]);c.beginPath();c.roundRect(sx+6,Y0+5,L-12,H-10,6);c.stroke();c.setLineDash([])}}
|
||||||
|
else{c.fillStyle=LI;c.beginPath();c.roundRect(sx-L,Y0-2,L,H+4,[10,0,0,10]);c.fill();c.stroke()
|
||||||
|
if(L>30){c.fillStyle=LE;c.lineWidth=4;for(const y of[16,40,64]){c.beginPath();c.roundRect(sx-L+8,Y0+y,L-16,18,3);c.fill();c.stroke()}}}
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.moveTo(sx,Y0-2);c.lineTo(sx,Y0+H+2);c.stroke()
|
||||||
|
hand(c,lp(sx+4,sx-W+4,o),Y0+H-24,-1);hand(c,sx+W-4,Y0+H-24,1)
|
||||||
|
c.restore()
|
||||||
|
if(dust>0&&dust<1){c.strokeStyle='#111';c.lineWidth=3;for(let k=0;k<6;k++){const a=-PI*(.1+.8*k/5),r=20+56*dust,x=sx+W/2+r*cos(a),y=Y0+24+r*sin(a)*.8,z=12*(1-dust)+3;c.fillStyle='#dee2e6';c.beginPath();c.arc(x,y,z,0,T);c.fill();c.stroke()}}
|
||||||
|
if(m>0&&m<1){const h=cl((m-.2)/.65),q=T*h*2,x=m<.2?lp(sx+W/2,150,io(m/.2)):m<.85?150+44*sin(q):lp(150,280,io((m-.85)/.15)),y=m<.2?lp(Y0+22,50,io(m/.2)):m<.85?50+12*sin(2*q):lp(50,10,(m-.85)/.15);c.save();c.translate(x,y);c.scale(1.5,1.5);moth(c,0,0,i%2?1:.3,.4*sin(T*m*2));c.restore()}
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// buttered toast flipping through the air and landing butter side down with a splat, then just lying there deadpan, every single time
|
||||||
|
const{sin,cos,PI,abs,min,max}=Math,T=2*PI
|
||||||
|
export const frames=30,delay=[...Array(29).fill(60),700],rim=4
|
||||||
|
const CR='#c97a2b',CM='#ffdf9e',BK='#f2bd6b',BU='#ffe14d',FL=206,LY=.38,PF=3*PI+Math.acos(LY),F=.36
|
||||||
|
// path is built under the squash, stroked after restore so lines stay even
|
||||||
|
const slice=(c,x,y,r,sx,sy,k)=>{c.save();c.translate(x,y);c.rotate(r);c.scale(sx*k,sy*k);c.beginPath();c.moveTo(-40,46);c.lineTo(-40,-10);c.quadraticCurveTo(-58,-18,-52,-36);c.quadraticCurveTo(-44,-58,0,-56);c.quadraticCurveTo(44,-58,52,-36);c.quadraticCurveTo(58,-18,40,-10);c.lineTo(40,46);c.quadraticCurveTo(40,52,34,52);c.lineTo(-34,52);c.quadraticCurveTo(-40,52,-40,46);c.closePath();c.restore()}
|
||||||
|
const toast=(c,x,y,cy,r,sx,bl,th=0)=>{
|
||||||
|
const back=cy<0,sy=abs(cy)
|
||||||
|
if(th){c.fillStyle='#a8611d';c.lineWidth=7;slice(c,x,y+th,r,sx,sy,1);c.fill();c.stroke()}
|
||||||
|
c.fillStyle=CR;c.lineWidth=7;slice(c,x,y,r,sx,sy,1);c.fill();c.stroke()
|
||||||
|
c.fillStyle=back?BK:CM;slice(c,x,y,r,sx,sy,.8);c.fill()
|
||||||
|
c.save();c.translate(x,y);c.rotate(r)
|
||||||
|
if(!back){c.save();c.scale(sx,sy);c.beginPath();c.roundRect(-22,-20,44,36,8);c.restore();c.fillStyle=BU;c.lineWidth=5;c.fill();c.stroke()
|
||||||
|
c.save();c.scale(sx,sy);c.beginPath();c.roundRect(-14,-12,12,6,3);c.restore();c.fillStyle='#fff';c.fill()}
|
||||||
|
else{c.scale(sx,max(.7,sy));c.lineWidth=5
|
||||||
|
for(const d of[-1,1])c.beginPath(),bl?(c.moveTo(d*16-8,-8),c.lineTo(d*16+8,-8)):(c.moveTo(d*16-9,-12),c.lineTo(d*16+9,-12),c.moveTo(d*16-5,-11),c.arc(d*16+1,-11,5.5,PI,0,true)),c.stroke()
|
||||||
|
c.beginPath();c.moveTo(-9,10);c.lineTo(9,10);c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t)=>{
|
||||||
|
const fall=min(1,t/F),e=fall*fall,ly=FL-24
|
||||||
|
c.fillStyle='#ced4da';c.beginPath();c.ellipse(128,FL+4,26+e*50,5+e*7,0,0,T);c.fill()
|
||||||
|
if(t<F){
|
||||||
|
const y=64+(ly-64)*e,p=PF*fall,x=128+16*sin(PI*fall)
|
||||||
|
if(fall>.15){c.lineWidth=5;for(const d of[-1,0,1])c.beginPath(),c.moveTo(x+d*34,y-70+abs(d)*12),c.lineTo(x+d*34,y-70+abs(d)*12-14-e*26),c.stroke()}
|
||||||
|
toast(c,x,y,cos(p),.3*sin(T*fall),1,0)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const u=(t-F)/(1-F),hit=max(0,1-u*7),sq=1+.16*hit,sp=min(1,u*5),sp2=1-(1-sp)**3
|
||||||
|
// butter splat squished out from under
|
||||||
|
c.fillStyle=BU;c.lineWidth=5;c.beginPath()
|
||||||
|
for(let k=0;k<=40;k++){const a=k/40*T,r=1+.14*sin(a*5+1)+.08*sin(a*9);c.lineTo(128+cos(a)*(44+54*sp2)*r,FL+2+sin(a)*(10+16*sp2)*r)}
|
||||||
|
c.closePath();c.fill();c.stroke()
|
||||||
|
for(const[x,y,s]of[[26,FL+22,6],[232,FL+16,7],[30,FL-12,5],[224,FL-14,5],[96,FL+36,5],[166,FL+36,4]]){const k=sp2;c.beginPath();c.ellipse(128+(x-128)*k,y,s*k+.5,s*.6*k+.5,0,0,T);c.fill();c.stroke()}
|
||||||
|
if(hit>0){c.lineWidth=5;for(const a of[-2.7,-2.2,-.95,-.45])c.beginPath(),c.moveTo(128+cos(a)*72,ly+10+sin(a)*26),c.lineTo(128+cos(a)*(72+36*hit),ly+10+sin(a)*(26+26*hit)),c.stroke()}
|
||||||
|
toast(c,128,FL-20+3*hit,-LY/sq,0,1.28*sq,u>.62&&u<.68,9)
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
// serene duck gliding along with its eyes closed humming a little tune, while under the water its legs are paddling like crazy
|
||||||
|
const{sin,cos,PI}=Math,T=2*PI
|
||||||
|
export const frames=12,delay=Array(12).fill(70),rim=4
|
||||||
|
const W='#4dabf7',WD='#1c7ed6',WL='#a5d8ff',DU='#fff',DS='#dee2e6',BK='#ff922b',LG='#fd7e14',SY=126
|
||||||
|
const leg=(c,x,y,a,col)=>{
|
||||||
|
const kx=x+cos(a)*20,ky=y+16+sin(a)*12,fx=kx+cos(a+1)*20,fy=ky+18+sin(a+1)*8
|
||||||
|
c.strokeStyle='#111';c.lineWidth=12;c.beginPath();c.moveTo(x,y);c.lineTo(kx,ky);c.lineTo(fx,fy);c.stroke()
|
||||||
|
c.strokeStyle=col;c.lineWidth=6;c.stroke()
|
||||||
|
c.fillStyle=col;c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.moveTo(fx,fy);c.lineTo(fx-24,fy+2+cos(a)*8);c.quadraticCurveTo(fx-20,fy+14,fx-8,fy+14);c.closePath();c.fill();c.stroke()
|
||||||
|
}
|
||||||
|
const body=c=>{c.beginPath();c.moveTo(48,96);c.quadraticCurveTo(70,104,90,104);c.bezierCurveTo(120,94,170,96,186,118);c.bezierCurveTo(196,140,170,156,128,156);c.bezierCurveTo(80,156,56,140,48,96)}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const g=4*sin(T*t),bob=Math.round(2*sin(2*T*t))
|
||||||
|
// water block
|
||||||
|
c.fillStyle=W;c.beginPath();c.moveTo(10,SY);for(let x=10;x<=246;x+=6)c.lineTo(x,SY+3*sin(x/14-T*t));c.lineTo(246,226);c.quadraticCurveTo(246,244,228,244);c.lineTo(28,244);c.quadraticCurveTo(10,244,10,226);c.closePath();c.fill();c.stroke()
|
||||||
|
// bubbles from all the effort
|
||||||
|
c.save();c.clip();c.fillStyle=WL;c.strokeStyle=WD;c.lineWidth=3
|
||||||
|
for(let k=0;k<5;k++){const p=(t*2+k/5)%1,x=60+((k*53)%130),y=238-p*96,r=3+(k%3)*2;c.beginPath();c.arc(x,y,r,0,T);c.fill();c.stroke()}
|
||||||
|
// whirl of motion where the legs are going round
|
||||||
|
c.strokeStyle=WL;c.lineWidth=5;for(const x of[112,140])for(let k=0;k<2;k++){const a=-T*t*3+k*PI;c.beginPath();c.arc(x-4,176,34-k*8,a,a+1.6);c.stroke()}
|
||||||
|
c.restore();c.strokeStyle='#111'
|
||||||
|
// frantic legs, pale ghost poses for blur
|
||||||
|
const a=-T*t*3
|
||||||
|
for(const[x,o]of[[112,0],[140,PI]]){leg(c,x,146+bob,a+o+1.2,'#ffd8a8');leg(c,x,146+bob,a+o+.6,'#ffa94d');leg(c,x,146+bob,a+o,LG)}
|
||||||
|
// effort marks
|
||||||
|
c.strokeStyle=WD;c.lineWidth=4;for(const[x,y,d]of[[62,170,-1],[58,192,-1],[192,170,1],[196,192,1]])c.beginPath(),c.moveTo(x+d*(i%2)*3,y),c.lineTo(x+d*(14+(i%2)*3),y-4*(y<180?1:-1)),c.stroke()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
// duck body, tinted below the surface
|
||||||
|
c.save();c.translate(0,bob);c.fillStyle=DU;c.lineWidth=7;body(c);c.fill();c.stroke()
|
||||||
|
c.save();body(c);c.clip();c.fillStyle=W;c.globalAlpha=.45;c.fillRect(0,SY-bob,256,80);c.globalAlpha=1;c.restore()
|
||||||
|
c.fillStyle=DS;c.lineWidth=5;c.beginPath();c.moveTo(96,116);c.quadraticCurveTo(126,108,150,118);c.quadraticCurveTo(128,134,100,126);c.closePath();c.fill();c.stroke()
|
||||||
|
// neck and head
|
||||||
|
c.fillStyle=DU;c.lineWidth=7;c.beginPath();c.moveTo(150,110);c.quadraticCurveTo(160,86,158,72);c.arc(176,64,24,PI*.85,PI*.42,false);c.quadraticCurveTo(184,100,184,116);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=DU;c.beginPath();c.arc(176,64,24,0,T);c.fill()
|
||||||
|
c.fillStyle=BK;c.lineWidth=6;c.beginPath();c.moveTo(196,58);c.quadraticCurveTo(226,58,228,68);c.quadraticCurveTo(222,78,196,74);c.closePath();c.fill();c.stroke()
|
||||||
|
c.beginPath();c.arc(176,64,24,-PI*.9,PI*.12);c.stroke()
|
||||||
|
// closed content eye and a little smile line on the beak
|
||||||
|
c.lineWidth=4;c.beginPath();c.arc(180,60,6,PI*1.1,PI*1.9);c.stroke()
|
||||||
|
c.fillStyle='#ffc9c9';c.beginPath();c.ellipse(182,76,6,3.5,0,0,T);c.fill()
|
||||||
|
c.restore()
|
||||||
|
// calm ripples at the waterline
|
||||||
|
c.strokeStyle=WL;c.lineWidth=4;for(const[x,d]of[[34,-1],[206,1]])c.beginPath(),c.moveTo(x-10-d*g,SY+6),c.lineTo(x+10-d*g,SY+6),c.stroke()
|
||||||
|
// floating note
|
||||||
|
const nx=206+6*sin(T*t),ny=40-t*16,ns=sin(PI*t)
|
||||||
|
c.save();c.translate(nx,ny);c.scale(ns,ns);c.fillStyle='#111';c.lineWidth=3.5;c.beginPath();c.ellipse(0,0,6,4.5,-.4,0,T);c.fill();c.beginPath();c.moveTo(5,-1);c.lineTo(5,-22);c.quadraticCurveTo(9,-14,15,-12);c.stroke();c.restore()
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
// office worker typing, the printer bursts into flames, he glances at it, looks at you, and quietly rolls his chair away to an identical desk
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=30,delay=90,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),lp=(a,b,u)=>a+(b-a)*u
|
||||||
|
const WALL='#d3f9d8',FLOOR='#b2f2bb',DESK='#e599f7',DD='#be4bdb',PR='#dee2e6',SKIN='#ffd3b0',HAIR='#343a40',SHIRT='#ffd43b',TIE='#4c6ef5',PANT='#495057',CHAIR='#4263eb',FIRE='#ff922b',FY='#ffe066'
|
||||||
|
const flame=(c,x,y,s,k)=>{c.save();c.translate(x,y);c.scale(s*(1+.08*sin(k*2.3)),s*(1+.15*sin(k*3.1)));c.fillStyle=FIRE;c.beginPath();c.moveTo(-16,0);c.quadraticCurveTo(-22,-20,-8,-36);c.quadraticCurveTo(-6,-22,0,-26);c.quadraticCurveTo(2,-44,12,-50);c.quadraticCurveTo(8,-30,18,-22);c.quadraticCurveTo(22,-10,16,0);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=FY;c.beginPath();c.moveTo(-8,0);c.quadraticCurveTo(-10,-14,0,-22);c.quadraticCurveTo(2,-12,8,-14);c.quadraticCurveTo(12,-6,8,0);c.closePath();c.fill();c.restore()}
|
||||||
|
const mod=(c,ox,fire,t,i)=>{
|
||||||
|
c.save();c.translate(ox,0);c.strokeStyle='#111';c.lineWidth=5
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.rect(18,40,52,40);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#74c0fc';c.beginPath();c.moveTo(22,76);c.lineTo(38,54);c.lineTo(48,66);c.lineTo(54,58);c.lineTo(66,76);c.closePath();c.fill()
|
||||||
|
c.lineWidth=6;c.fillStyle=DESK;c.beginPath();c.rect(100,150,82,10);c.fill();c.stroke()
|
||||||
|
c.fillStyle=DD;c.beginPath();c.rect(106,160,12,64);c.rect(164,160,12,64);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#495057';c.beginPath();c.roundRect(114,92,56,40,6);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#a5d8ff';c.beginPath();c.rect(120,98,44,28);c.fill();c.lineWidth=4;c.beginPath();c.moveTo(142,132);c.lineTo(142,148);c.moveTo(130,148);c.lineTo(154,148);c.stroke()
|
||||||
|
c.lineWidth=6;c.fillStyle='#adb5bd';c.beginPath();c.rect(190,176,48,48);c.fill();c.stroke()
|
||||||
|
const sh=fire?cl((t-.14)/.06)*(1-cl((t-.26)/.02))*2*sin(i*2.7):0
|
||||||
|
c.save();c.translate(214+sh,176);c.fillStyle=PR;c.beginPath();c.roundRect(-22,-30,44,30,5);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.rect(-12,-40,24,10);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#212529';c.beginPath();c.rect(-14,-16,28,5);c.fill()
|
||||||
|
c.fillStyle=fire&&t>.12&&t<.3&&i%2?'#fa5252':'#51cf66';c.beginPath();c.arc(14,-22,3,0,T);c.fill()
|
||||||
|
if(fire&&t>.2){c.strokeStyle='#111';c.lineWidth=4;const f=cl((t-.26)/.06);for(let k=0;k<3;k++){const p=(t*3+k/3)%1,r=6+10*p;c.fillStyle='#868e96';c.beginPath();c.arc(-6+10*k-8*p,-60-56*p,r,0,T);c.fill();c.stroke()}
|
||||||
|
if(f>0)flame(c,8,-26,f*.9,i+2),flame(c,-8,-28,f*1.15,i)}
|
||||||
|
c.restore();c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const ox=256*io((t-.5)/.32),look=io((t-.29)/.04)*(1-io((t-.36)/.04)),cam=io((t-.37)/.04)*(1-io((t-.5)/.06)),push=io((t-.46)/.05)*(1-io((t-.53)/.08))
|
||||||
|
const typ=t<.28||t>.9,away=t>.5&&t<.86?sin(PI*(t-.5)/.36):0,wx=lp(80,66,away)-10*push+4*io((t-.84)/.06)-4*io((t-.84)/.06),bl=i==13
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=WALL;c.fill();c.clip()
|
||||||
|
c.fillStyle=FLOOR;c.fillRect(0,222,256,40);c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.moveTo(0,222);c.lineTo(256,222);c.stroke()
|
||||||
|
mod(c,ox,1,t,i);mod(c,ox-256,0,t,i)
|
||||||
|
if(away>.2){c.strokeStyle='#40c057';c.lineWidth=5;c.beginPath();for(const[y,l]of[[120,30],[170,44],[200,24]])c.moveTo(wx+60,y),c.lineTo(wx+60+l*away,y);c.stroke()}
|
||||||
|
const tl=-.12*away,x=wx,y=0
|
||||||
|
c.save();c.translate(x,0);c.rotate(tl*.2);c.strokeStyle='#111';c.lineWidth=6
|
||||||
|
const sp=t*T*6*(away>0)
|
||||||
|
c.lineWidth=6;c.beginPath();c.moveTo(0,176);c.lineTo(0,208);c.moveTo(-26,212);c.lineTo(26,212);c.stroke()
|
||||||
|
c.fillStyle='#212529';c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.arc(d*24,218,6,0,T),c.fill(),c.stroke()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=2;for(const d of[-1,1])c.beginPath(),c.moveTo(d*24,218),c.lineTo(d*24+5*cos(sp),218+5*sin(sp)),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=CHAIR
|
||||||
|
c.beginPath();c.roundRect(-30,164,64,14,6);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(-40,96,16,76,8);c.fill();c.stroke()
|
||||||
|
for(const[w,s]of[[22,'#111'],[13,PANT]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(-6,158),c.lineTo(34,158),c.lineTo(36,206),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle='#212529';c.beginPath();c.ellipse(44,210,13,7,0,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=6;c.fillStyle=SHIRT;c.beginPath();c.moveTo(-22,166);c.lineTo(-20,112);c.quadraticCurveTo(-18,96,0,96);c.quadraticCurveTo(18,96,20,112);c.lineTo(22,166);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=TIE;c.lineWidth=4;c.beginPath();c.moveTo(4,100);c.lineTo(12,100);c.lineTo(14,130);c.lineTo(8,138);c.lineTo(2,130);c.closePath();c.fill();c.stroke()
|
||||||
|
const hb=typ?2*sin(t*T*20):0,ax=lp(60,72,push)+hb,ay=lp(146,140,push)
|
||||||
|
for(const[w,s]of[[20,'#111'],[11,SHIRT]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(4,110),c.quadraticCurveTo(14,146,away>.1?30:ax-10,away>.1?150:ay),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=SKIN;c.beginPath();c.arc(away>.1?34:ax-6,away>.1?150:ay,7.5,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.translate(2,66);c.lineWidth=6;c.fillStyle=SKIN;c.beginPath();c.arc(0,0,30,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HAIR;c.beginPath();c.moveTo(-30,4);c.quadraticCurveTo(-34,-34,2,-32);c.quadraticCurveTo(30,-32,30,-12);c.quadraticCurveTo(10,-20,-8,-14);c.quadraticCurveTo(-16,-4,-30,4);c.fill();c.stroke()
|
||||||
|
const ex=lp(lp(12,16,look),-2,cam),ey=lp(2,-4,look)+3*cam
|
||||||
|
c.fillStyle='#111';c.strokeStyle='#111';c.lineWidth=4
|
||||||
|
for(const d of[-1,1]){if(bl)c.beginPath(),c.moveTo(ex+d*10-5,ey),c.lineTo(ex+d*10+5,ey),c.stroke();else c.beginPath(),c.arc(ex+d*10,ey,4,0,T),c.fill()
|
||||||
|
c.beginPath();c.moveTo(ex+d*10-6,ey-8+2*cam);c.lineTo(ex+d*10+6,ey-8);c.stroke()}
|
||||||
|
c.beginPath();c.moveTo(ex-6,ey+16);c.lineTo(ex+6,ey+16);c.stroke()
|
||||||
|
if(cam>.5){c.fillStyle='#74c0fc';c.lineWidth=3;c.beginPath();c.moveTo(-24,-12);c.quadraticCurveTo(-18,-2,-24,2);c.quadraticCurveTo(-30,-2,-24,-12);c.fill();c.stroke()}
|
||||||
|
c.restore();c.restore()
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// someone off-screen explains charts and jargon while a guy smiles politely and nods along, his thought bubble pure tv static
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=16,delay=90,rim=3
|
||||||
|
const BG='#fff0f6',SKIN='#ffd3b0',HAIR='#e8590c',SH='#20c997',SB='#fff',TX='#868e96'
|
||||||
|
const rnd=s=>{s=sin(s*127.1)*43758.5453;return s-Math.floor(s)}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const nd=max(0,sin(T*t*2))**1.5,hx=150,hy=168+8*nd,tilt=.06*nd
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=BG;c.fill();c.clip()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=SB
|
||||||
|
c.beginPath();c.moveTo(-4,64);c.lineTo(20,54);c.lineTo(20,24);c.quadraticCurveTo(20,16,28,16);c.lineTo(110,16);c.quadraticCurveTo(118,16,118,24);c.lineTo(118,100);c.quadraticCurveTo(118,108,110,108);c.lineTo(28,108);c.quadraticCurveTo(20,108,20,100);c.lineTo(20,74);c.closePath();c.fill();c.stroke()
|
||||||
|
c.save();c.beginPath();c.rect(24,20,90,84);c.clip()
|
||||||
|
const sc=t*96
|
||||||
|
for(let k=0;k<8;k++){
|
||||||
|
const y=26+k*24-sc%24,n=Math.floor(sc/24)+k
|
||||||
|
if(n%4==2){c.fillStyle='#4dabf7';c.lineWidth=3;for(let b=0;b<4;b++){const h=6+14*rnd(n*7+b);c.beginPath();c.rect(32+b*14,y+16-h,10,h);c.fill();c.stroke()}c.strokeStyle='#e64980';c.lineWidth=3;c.beginPath();c.moveTo(92,y+16);c.lineTo(98,y+4);c.lineTo(104,y+10);c.lineTo(110,y-2);c.stroke();c.strokeStyle='#111'}
|
||||||
|
else{c.strokeStyle=TX;c.lineWidth=6;c.beginPath();let x=32;while(x<104){const w=8+18*rnd(n*13+x);c.moveTo(x,y+6);c.lineTo(min(x+w,106),y+6);x+=w+10}c.stroke();c.strokeStyle='#111'}
|
||||||
|
}
|
||||||
|
c.restore()
|
||||||
|
c.lineWidth=6;c.fillStyle=SH;c.beginPath();c.moveTo(70,262);c.quadraticCurveTo(72,216,hx,212);c.quadraticCurveTo(228,216,232,262);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.moveTo(hx,226),c.lineTo(hx+d*22,212),c.lineTo(hx+d*6,208),c.closePath(),c.fill(),c.stroke()
|
||||||
|
c.save();c.translate(hx,hy);c.rotate(tilt)
|
||||||
|
c.lineWidth=6;c.fillStyle=SKIN;c.beginPath();c.ellipse(-46,6,9,13,0,0,T);c.ellipse(46,6,9,13,0,0,T);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.arc(0,0,46,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HAIR;c.beginPath();c.moveTo(-46,-2);c.quadraticCurveTo(-50,-50,-4,-48);c.quadraticCurveTo(44,-50,46,-4);c.quadraticCurveTo(30,-22,10,-20);c.quadraticCurveTo(14,-30,6,-34);c.quadraticCurveTo(-6,-20,-26,-18);c.quadraticCurveTo(-40,-14,-46,-2);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.arc(d*17-4,2,10,0,T),c.fill(),c.stroke()
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*17-7,3,3.5,0,T),c.fill()
|
||||||
|
c.lineWidth=4;c.beginPath();for(const d of[-1,1])c.moveTo(d*17-12,-16+d*0),c.quadraticCurveTo(d*17-4,-22,d*17+4,-16);c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(-20,22);c.quadraticCurveTo(-4,32,14,22);c.stroke()
|
||||||
|
c.lineWidth=3;c.beginPath();c.moveTo(-22,19);c.lineTo(-19,25);c.moveTo(16,19);c.lineTo(13,25);c.stroke()
|
||||||
|
c.fillStyle='#ffa8a8';for(const d of[-1,1])c.beginPath(),c.ellipse(d*28-4,16,7,4,0,0,T),c.fill()
|
||||||
|
const sd=(t*2)%1;c.fillStyle='#74c0fc';c.lineWidth=3;c.beginPath();c.moveTo(38,-26+sd*10);c.quadraticCurveTo(46,-12+sd*10,38,-8+sd*10);c.quadraticCurveTo(30,-12+sd*10,38,-26+sd*10);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle='#fff'
|
||||||
|
for(const[x,y,r]of[[176,116,6],[188,102,9]])c.beginPath(),c.arc(x,y,r,0,T),c.fill(),c.stroke()
|
||||||
|
const B=[[166,56,30],[196,44,30],[222,62,24],[204,80,26],[170,82,24],[148,68,22]]
|
||||||
|
c.lineWidth=12;for(const[x,y,r]of B)c.beginPath(),c.arc(x,y,r,0,T),c.stroke()
|
||||||
|
c.save();c.beginPath();for(const[x,y,r]of B)c.moveTo(x+r,y),c.arc(x,y,r,0,T);c.clip()
|
||||||
|
const G=['#495057','#868e96','#ced4da','#f8f9fa','#212529'],Z=7
|
||||||
|
for(let y=14;y<112;y+=Z)for(let x=120;x<250;x+=Z){c.fillStyle=G[Math.floor(rnd(x*.13+y*7.7+i*31.3)*5)];c.fillRect(x,y,Z,Z)}
|
||||||
|
const by=14+((t*3)%1)*98;c.fillStyle='rgba(255,255,255,.35)';c.fillRect(120,by,130,10)
|
||||||
|
c.restore()
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// a little guy sits resigned in a simmering pot, a parsley sprig lands on his head as garnish and he blows it off with a sigh: WE'RE COOKED
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=28,delay=90,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)}
|
||||||
|
const G={W:'002c558ca0',E:'80000c8c 0666',"'":'0003',R:'0c006082856707 478c'," ":'',C:'826020020a2c6c8a',O:'2060828a6c2c0a0220',K:'000c 8007 358c',D:'005083895c0c00'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const WY=156
|
||||||
|
const tongue=(c,x,y,w,h,col)=>{c.fillStyle=col;c.beginPath();c.moveTo(x-w/2,y);c.quadraticCurveTo(x-w/2,y-h*.6,x,y-h);c.quadraticCurveTo(x+w/2,y-h*.6,x+w/2,y);c.closePath();c.fill();c.stroke()}
|
||||||
|
const parsley=(c,x,y,r)=>{c.save();c.translate(x,y);c.rotate(r);c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(4,10,2,18);c.stroke()
|
||||||
|
c.fillStyle='#40c057';c.lineWidth=3.5;for(const[a,b,s]of[[-9,-4,8],[8,-5,8],[0,-12,9],[-3,2,6],[5,3,6]])c.beginPath(),c.arc(a,b,s,0,T),c.fill(),c.stroke()
|
||||||
|
for(const[a,b,s]of[[-9,-4,8],[8,-5,8],[0,-12,9],[-3,2,6],[5,3,6]])c.beginPath(),c.arc(a,b,s-2,0,T),c.fill();c.restore()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const ta=(i>>1)*2/frames,bob=0,land=t>=.42&&t<.82,fall=ez(t,.28,.42),blow=ez(t,.8,.92),pf=t>.76&&t<.86
|
||||||
|
// burner flames
|
||||||
|
c.lineWidth=4;c.strokeStyle='#111';for(const[k,x]of[[0,90],[1,128],[2,166]]){const h=20+5*sin(ta*T*3+k*2);tongue(c,x,250,24,h,'#4dabf7');tongue(c,x,250,12,h*.55,'#d0ebff')}
|
||||||
|
// pot back rim and water
|
||||||
|
c.fillStyle='#868e96';c.lineWidth=6;c.beginPath();c.ellipse(128,WY,86,16,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#a5d8ff';c.beginPath();c.ellipse(128,WY+2,76,11,0,0,T);c.fill()
|
||||||
|
// the guy, in up to his chest
|
||||||
|
c.save();c.translate(128,bob)
|
||||||
|
c.fillStyle='#fff';c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.moveTo(-34,WY+2);c.bezierCurveTo(-40,36,40,36,34,WY+2);c.fill();c.stroke()
|
||||||
|
// arms resting along the rim
|
||||||
|
for(const d of[-1,1]){for(const[w,s]of[[12,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(d*32,WY-26),c.quadraticCurveTo(d*56,WY-26,d*74,WY-10-bob),c.stroke()}
|
||||||
|
c.strokeStyle='#111';c.fillStyle='#fff';c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.arc(d*76,WY-8-bob,7,0,T),c.fill(),c.stroke()
|
||||||
|
// deadpan face, glances up at the garnish
|
||||||
|
const up=land&&t<.62?1:0,hy=WY-56
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*11,hy+(up?-3:2),3.6,0,T),c.fill()
|
||||||
|
c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.moveTo(d*4,hy-4),c.lineTo(d*18,hy-4),c.stroke()
|
||||||
|
if(pf){c.fillStyle='#fff';c.lineWidth=3.5;c.beginPath();c.ellipse(4,hy+20,6,5,0,0,T);c.fill();c.stroke()}
|
||||||
|
else{c.lineWidth=4;c.beginPath();c.moveTo(-8,hy+20);c.lineTo(8,hy+20);c.stroke()}
|
||||||
|
c.fillStyle='#74c0fc';c.lineWidth=3;const sy=hy-18;c.beginPath();c.moveTo(26,sy-9);c.quadraticCurveTo(32,sy,32,sy+3);c.arc(26,sy+3,6,0,PI);c.quadraticCurveTo(20,sy,26,sy-9);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// water line over him, bubbles and floating veg
|
||||||
|
c.fillStyle='#a5d8ff';c.strokeStyle='#111';c.beginPath();c.ellipse(128,WY+6,76,8,0,0,PI);c.lineTo(52,WY+2);c.fill()
|
||||||
|
c.lineWidth=3;c.fillStyle='#e7f5ff';for(let k=0;k<5;k++){const u=(ta*2+k/5)%1,x=60+k*34+(k%2?6:-6),s=4+5*sin(PI*u);if(abs(x-128)<38)continue;c.beginPath();c.arc(x,WY+3-2*u,s,0,T);c.fill();c.stroke()}
|
||||||
|
c.lineWidth=3;c.fillStyle='#ff922b';c.beginPath();c.ellipse(76,WY+4+1.5*sin(ta*T*2+1),9,4,0,0,T);c.fill();c.stroke();c.fillStyle='#ffc078';c.beginPath();c.ellipse(76,WY+4+1.5*sin(ta*T*2+1),4,1.8,0,0,T);c.fill()
|
||||||
|
c.fillStyle='#8ce99a';c.beginPath();c.ellipse(178,WY+5+1.5*sin(ta*T*2+3),8,3.5,0,0,T);c.fill();c.stroke()
|
||||||
|
// pot front
|
||||||
|
c.fillStyle='#ced4da';c.lineWidth=7;c.beginPath();c.moveTo(42,WY);c.ellipse(128,WY,86,16,0,PI,0,true);c.lineTo(214,WY);c.lineTo(206,226);c.quadraticCurveTo(204,238,190,238);c.lineTo(66,238);c.quadraticCurveTo(52,238,50,226);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#adb5bd';c.lineWidth=5;c.beginPath();c.moveTo(46,192);c.lineTo(210,192);c.lineTo(209,204);c.lineTo(47,204);c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.moveTo(62,180);c.lineTo(64,224);c.stroke();c.strokeStyle='#111'
|
||||||
|
c.fillStyle='#495057';c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.roundRect(d>0?212:20,WY+12,24,12,6),c.fill(),c.stroke()
|
||||||
|
// steam
|
||||||
|
c.lineCap='round';for(const[k,x]of[[0,66],[1,190]]){const u=(ta*2+k*.5)%1,y=WY-52-40*u,a=1-u
|
||||||
|
if(u>.85)continue;for(const[w,s]of[[11,'#111'],[5,'#fff']]){c.lineWidth=w*a+2;c.strokeStyle=s;c.beginPath();c.moveTo(x,y+22);c.bezierCurveTo(x-10,y+12,x+10,y+4,x,y-8);c.stroke()}}
|
||||||
|
// parsley garnish falls, sits on his head, gets blown away
|
||||||
|
if(t>=.28&&t<.95){let px=128+4,py=-20+(WY-100+bob+20)*fall,r=2*PI*(1-fall)*.8
|
||||||
|
if(t>=.8){px+=90*blow;py-=120*blow+30*sin(PI*blow);r=4*blow}
|
||||||
|
if(land&&t<.5)py+=2*sin((t-.42)*T*6)
|
||||||
|
parsley(c,px,py,r)}
|
||||||
|
txt(c,"WE'RE COOKED",128,22,18,'#fff')
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// a proud chef presents a charred, still-burning roast under a blaring smoke alarm and blows a chef's kiss
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=85,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),lp=(a,b,u)=>a+(b-a)*u
|
||||||
|
const WALL='#ffe8cc',TILE='#ffd8a8',CTR='#868e96',SKIN='#ffd3b0',JK='#fff',MU='#5c3d2e',BURN='#2b2b2b',SMK='#ced4da',FIRE='#ff922b',FY='#ffd43b'
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const up=io((t-.3)/.14)-io((t-.62)/.12),fl=io((t-.5)/.08)*(1-io((t-.66)/.12)),kiss=up>.6&&fl<.3,bob=0,bl=i%4<2
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=WALL;c.fill();c.clip()
|
||||||
|
c.fillStyle=TILE;c.fillRect(0,150,256,80);c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.moveTo(0,150);c.lineTo(256,150);c.stroke()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
c.fillStyle=CTR;c.lineWidth=6;c.beginPath();c.rect(-10,226,276,40);c.fill();c.stroke()
|
||||||
|
c.save();c.translate(128,0)
|
||||||
|
c.fillStyle=JK;c.beginPath();c.moveTo(-58,262);c.lineTo(-52,170);c.quadraticCurveTo(-46,140,0,138);c.quadraticCurveTo(46,140,52,170);c.lineTo(58,262);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ff6b6b';c.beginPath();c.moveTo(-20,140);c.lineTo(20,140);c.lineTo(10,160);c.lineTo(0,152);c.lineTo(-10,160);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';for(const x of[-14,14])for(const y of[180,204])c.beginPath(),c.arc(x,y,4,0,T),c.fill()
|
||||||
|
c.restore()
|
||||||
|
c.save();c.translate(128,96+bob*.4)
|
||||||
|
c.lineWidth=6;c.fillStyle=SKIN;c.beginPath();c.arc(0,0,36,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.moveTo(-30,-22);c.lineTo(-28,-40);c.arc(-18,-52,16,PI*.75,PI*1.6);c.arc(2,-64,20,PI*1.1,PI*1.9);c.arc(22,-52,16,PI*1.4,PI*.25);c.lineTo(30,-22);c.closePath();c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(-32,-30,64,14,4);c.fill();c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();for(const d of[-1,1])c.arc(d*14,4,7,PI*1.15,PI*1.85);c.stroke()
|
||||||
|
c.fillStyle='#ff8fa3';for(const d of[-1,1])c.beginPath(),c.ellipse(d*24,14,7,4.5,0,0,T),c.fill()
|
||||||
|
c.lineWidth=4;if(kiss){c.fillStyle='#e8590c';c.beginPath();c.arc(0,27,4.5,0,T);c.fill();c.stroke()}else{c.fillStyle='#c92a2a';c.beginPath();c.moveTo(-9,22);c.quadraticCurveTo(0,34,9,22);c.closePath();c.fill();c.stroke()}
|
||||||
|
c.fillStyle=MU;c.beginPath();c.moveTo(0,15);c.bezierCurveTo(-8,10,-18,12,-20,16);c.bezierCurveTo(-24,14,-26,10,-22,6);c.bezierCurveTo(-28,8,-28,20,-18,21);c.bezierCurveTo(-10,22,-4,19,0,18);c.bezierCurveTo(4,19,10,22,18,21);c.bezierCurveTo(28,20,28,8,22,6);c.bezierCurveTo(26,10,24,14,20,16);c.bezierCurveTo(18,12,8,10,0,15);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
const px=72,py=176+bob
|
||||||
|
for(const[w,s]of[[22,'#111'],[12,JK]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(84,154),c.quadraticCurveTo(70,186,px+10,py+6),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle='#fff';c.beginPath();c.ellipse(px,py,52,13,0,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=3;c.strokeStyle='#adb5bd';c.beginPath();c.ellipse(px,py-1,36,7,0,0,T);c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6
|
||||||
|
c.fillStyle=BURN;c.beginPath();c.moveTo(px-38,py-2);c.bezierCurveTo(px-42,py-30,px-16,py-38,px,py-38);c.bezierCurveTo(px+16,py-38,px+42,py-30,px+38,py-2);c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#5c5f66';c.lineWidth=4;c.beginPath();c.moveTo(px-22,py-24);c.lineTo(px-12,py-28);c.lineTo(px-6,py-22);c.moveTo(px+8,py-26);c.lineTo(px+18,py-22);c.stroke()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
for(const d of[-1,1]){c.save();c.translate(px+d*26,py-6);c.rotate(d*1.05);c.lineWidth=5;c.fillStyle=BURN;c.beginPath();c.ellipse(0,-6,10,13,0,0,T);c.fill();c.stroke();c.fillStyle='#fff';c.beginPath();c.roundRect(-3.5,-30,7,16,2);c.fill();c.stroke();for(const e of[-1,1])c.beginPath(),c.arc(e*4.5,-31,5,0,T),c.fill(),c.stroke();c.restore()}
|
||||||
|
const f=1+.18*sin(T*t*7)
|
||||||
|
c.save();c.translate(px+4,py-36);c.scale(.8,.8*f);c.strokeStyle='#111';c.lineWidth=4;c.fillStyle=FIRE;c.beginPath();c.moveTo(-12,0);c.quadraticCurveTo(-14,-16,-2,-30);c.quadraticCurveTo(0,-18,6,-20);c.quadraticCurveTo(14,-12,12,0);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=FY;c.beginPath();c.moveTo(-5,0);c.quadraticCurveTo(-6,-10,0,-16);c.quadraticCurveTo(6,-8,5,0);c.closePath();c.fill();c.restore()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5
|
||||||
|
for(let k=0;k<3;k++){const p=(t+k/3)%1,x=px+4+10*sin(T*(p+k*.3))-18*p,y=py-62-p*130,r=10+12*p,B=[[0,0,r],[r*.8,r*.4,r*.7],[-r*.7,r*.45,r*.65]];c.fillStyle='#111';for(const[a,b,q]of B)c.beginPath(),c.arc(x+a,y+b,q+5,0,T),c.fill();c.fillStyle=SMK;for(const[a,b,q]of B)c.beginPath(),c.arc(x+a,y+b,q,0,T),c.fill();c.fillStyle='#e9ecef';c.beginPath();c.arc(x-r*.3,y-r*.3,r*.35,0,T);c.fill()}
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle='#fff';c.beginPath();c.ellipse(64,6,32,24,0,0,PI);c.fill();c.stroke()
|
||||||
|
c.fillStyle=bl?'#fa5252':'#862e2e';c.lineWidth=4;c.beginPath();c.arc(64,18,6.5,0,T);c.fill();c.stroke()
|
||||||
|
if(bl){c.strokeStyle='#fa5252';c.lineWidth=5;for(const r of[38,50])for(const d of[-1,1])c.beginPath(),c.arc(64,8,r,PI/2-d*.6-.3,PI/2-d*.6+.3),c.stroke()}
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
const hx=lp(186,140,up)+lp(0,60,fl),hy=lp(206,124,up)+lp(0,-34,fl)
|
||||||
|
for(const[w,s]of[[22,'#111'],[12,JK]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(174,156),c.quadraticCurveTo(lp(198,190,up),lp(196,176,up),hx,hy),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=SKIN
|
||||||
|
if(fl>.3){c.save();c.translate(hx,hy);c.rotate(-.4);c.beginPath();c.arc(0,0,10,0,T);c.fill();c.stroke();for(let k=0;k<4;k++){c.save();c.rotate(-1.2+k*.5);c.beginPath();c.roundRect(6,-3.5,14,7,3.5);c.fill();c.stroke();c.restore()}c.restore()
|
||||||
|
c.fillStyle=FY;c.lineWidth=3;for(const[a,r,s]of[[-1.1,36,1],[-.3,42,.85],[.5,34,.75]]){const sx=hx+r*cos(a)*fl,sy=hy+r*sin(a)*fl-10,z=13*s*fl;c.beginPath();for(let k=0;k<8;k++){const q=k*PI/4,rr=k%2?z*.35:z;c.lineTo(sx+rr*cos(q),sy+rr*sin(q))}c.closePath();c.fill();c.stroke()}}
|
||||||
|
else{c.beginPath();c.arc(hx,hy,10,0,T);c.fill();c.stroke();c.beginPath();c.ellipse(hx-4,hy-10,4,7,-.3,0,T);c.fill();c.stroke()}
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// a calm guy's thought bubble replays the day he waved back at someone who was waving at the person behind him, and he cringes all over
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=40,delay=75,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),lp=(a,b,u)=>a+(b-a)*u
|
||||||
|
const BG='#e7f5ff',SKIN='#ffd3b0',HAIR='#5c3d2e',ME='#ff922b',A='#4dabf7',B='#da77f2',RED='#ff6b6b'
|
||||||
|
const fig=(c,x,col,hair,d,arm,face)=>{
|
||||||
|
c.save();c.translate(x,134);c.scale(1.3,1.3);c.strokeStyle='#111';c.lineWidth=4
|
||||||
|
c.beginPath();c.moveTo(-5,-14);c.lineTo(-6,0);c.moveTo(5,-14);c.lineTo(6,0);c.stroke()
|
||||||
|
const sx=d*8,sy=-30,ax=sx+d*13*cos(arm),ay=sy-13*sin(arm),hx=ax+d*10*cos(arm+.5),hy=ay-10*sin(arm+.5)
|
||||||
|
for(const[w,s]of[[11,'#111'],[5,col]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(sx,sy),c.lineTo(ax,ay),c.lineTo(hx,hy),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=4;c.fillStyle=SKIN;c.beginPath();c.arc(hx,hy,4.5,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=col;c.beginPath();c.roundRect(-10,-36,20,24,7);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SKIN;c.beginPath();c.arc(0,-46,11,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=hair;c.beginPath();c.arc(0,-48,11,PI*1.05,PI*1.95);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';for(const e of[2,8])c.beginPath(),c.arc(d*e-d*2,-45,1.8,0,T),c.fill()
|
||||||
|
c.lineWidth=2.5;c.beginPath();if(face==1)c.arc(d*3,-41,3.5,.1*PI,.9*PI);else if(face==2)c.moveTo(d*1,-39),c.lineTo(d*6,-39);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const bub=io((t-.05)/.08)*(1-io((t-.86)/.08)),cr=io((t-.47)/.05)*(1-io((t-.86)/.07)),sk=cr>.3?3*sin(i*2.6):0
|
||||||
|
const wa=sin(T*t*8)*.4,meUp=io((t-.2)/.04)*(1-io((t-.56)/.08)),bIn=io((t-.3)/.08),freeze=t>.42
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=BG;c.fill();c.clip()
|
||||||
|
c.lineWidth=6;c.strokeStyle='#111';c.fillStyle=ME;c.beginPath();c.moveTo(-6,262);c.quadraticCurveTo(-2,222,66,220-10*cr);c.quadraticCurveTo(134,222,140,262);c.closePath();c.fill();c.stroke()
|
||||||
|
c.save();c.translate(66+sk,194+6*cr);c.rotate(sk*.01)
|
||||||
|
c.fillStyle=SKIN;c.lineWidth=6;c.beginPath();c.arc(0,0,44,0,T);c.fill();c.stroke()
|
||||||
|
if(cr>.01){c.fillStyle=`rgba(255,107,107,${(.55*cr).toFixed(2)})`;c.beginPath();c.arc(0,0,41,0,T);c.fill()}
|
||||||
|
c.fillStyle=HAIR;c.beginPath();c.moveTo(-44,-4);c.quadraticCurveTo(-48,-48,0,-46);c.quadraticCurveTo(46,-48,44,-4);c.quadraticCurveTo(36,-26,14,-26);c.lineTo(6,-18);c.lineTo(-2,-28);c.quadraticCurveTo(-34,-26,-44,-4);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.strokeStyle='#111';c.lineWidth=5
|
||||||
|
if(cr>.5){for(const d of[-1,1])c.beginPath(),c.moveTo(d*26,-4),c.lineTo(d*12,2),c.lineTo(d*26,8),c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.roundRect(-16,16,32,14,4);c.fill();c.stroke();c.beginPath();c.moveTo(-16,23);c.lineTo(16,23);for(const x of[-8,0,8])c.moveTo(x,16),c.lineTo(x,30);c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();for(const d of[-1,1])c.moveTo(d*28,-16),c.lineTo(d*12,-10);c.stroke()}
|
||||||
|
else{const lx=6*bub,ly=-5*bub;for(const d of[-1,1])c.beginPath(),c.arc(d*16+lx,2+ly,5,0,T),c.fill()
|
||||||
|
c.lineWidth=4;c.beginPath();c.arc(lx*.5,16,11,.15*PI,.85*PI);c.stroke()
|
||||||
|
c.fillStyle='#ffa8a8';for(const d of[-1,1])c.beginPath(),c.ellipse(d*28,16,7,4,0,0,T),c.fill()}
|
||||||
|
c.restore()
|
||||||
|
if(cr>.3){c.strokeStyle=RED;c.lineWidth=5;for(const[x,y,a]of[[20,140,-2.2],[116,150,-.9],[124,196,0],[4,192,PI]]){c.save();c.translate(x+sk,y);c.rotate(a);c.beginPath();for(let k=0;k<=12;k++)c.lineTo(k*2.4,4*sin(k*1.4+i*1.8));c.stroke();c.restore()}}
|
||||||
|
if(bub>.01){
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle='#fff'
|
||||||
|
for(const[x,y,r,k]of[[98,158,6,.2],[108,144,8,.5]])if(bub>k)c.beginPath(),c.arc(x,y,r,0,T),c.fill(),c.stroke()
|
||||||
|
c.save();c.translate(166,84);c.scale(bub,bub);c.translate(-166,-84)
|
||||||
|
const C=[[112,66,30],[152,44,30],[196,44,28],[220,76,22],[212,110,26],[166,120,28],[118,108,28],[166,80,54]]
|
||||||
|
c.lineWidth=12;for(const[x,y,r]of C)c.beginPath(),c.arc(x,y,r,0,T),c.stroke()
|
||||||
|
c.fillStyle='#fff';for(const[x,y,r]of C)c.beginPath(),c.arc(x,y,r,0,T),c.fill()
|
||||||
|
c.save();c.beginPath();for(const[x,y,r]of C)c.moveTo(x+r,y),c.arc(x,y,r,0,T);c.clip()
|
||||||
|
c.strokeStyle='#adb5bd';c.lineWidth=4;c.beginPath();c.moveTo(80,134);c.lineTo(250,134);c.stroke()
|
||||||
|
fig(c,112,A,'#343a40',1,1.2+(t<.62?wa:0),1)
|
||||||
|
fig(c,lp(266,218,bIn),B,'#f08c00',-1,bIn>.5?1.2-wa:-1.5,1)
|
||||||
|
fig(c,166,ME,HAIR,-1,meUp>.01?lp(-1.5,1.3+(freeze?0:wa*.7),meUp):-1.5,freeze?2:1)
|
||||||
|
if(t>.42&&t<.6){c.fillStyle='#111';c.save();c.translate(176,44);c.beginPath();c.roundRect(-3.5,-16,7,16,3.5);c.fill();c.beginPath();c.arc(0,5,3.5,0,T);c.fill();c.restore()}
|
||||||
|
c.restore();c.restore()
|
||||||
|
}
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
// a panicked little guy sprints for his life while a giant red line spelling DEADLINE closes in behind him, calendar pages flying past
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=15,delay=65,rim=3
|
||||||
|
const BG='#fff3bf',GR='#ffe066',RED='#f03e3e',SH='#4dabf7',PA='#495057',SKIN='#ffd3b0',HAIR='#5c3d2e'
|
||||||
|
const G={D:[[[0,0],[0,6],[2,6],[3.4,5],[4,3],[3.4,1],[2,0],[0,0]]],E:[[[4,0],[0,0],[0,6],[4,6]],[[0,3],[3,3]]],A:[[[0,6],[2,0],[4,6]],[[.9,3.8],[3.1,3.8]]],L:[[[0,0],[0,6],[4,6]]],I:[[[2,0],[2,6]],[[1,0],[3,0]],[[1,6],[3,6]]],N:[[[0,6],[0,0],[4,6],[4,0]]]}
|
||||||
|
const glyph=(c,ch,x,y,s)=>{c.beginPath();for(const l of G[ch])l.forEach(([a,b],k)=>c[k?'lineTo':'moveTo'](x+a*s,y+b*s))}
|
||||||
|
const limb=(c,x,y,a1,l1,a2,l2,col,w)=>{const kx=x+l1*sin(a1),ky=y+l1*cos(a1),fx=kx+l2*sin(a2),fy=ky+l2*cos(a2);for(const[lw,s]of[[w+8,'#111'],[w,col]])c.lineWidth=lw,c.strokeStyle=s,c.beginPath(),c.moveTo(x,y),c.lineTo(kx,ky),c.lineTo(fx,fy),c.stroke();return[fx,fy]}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const f=T*3*t,bx=58+26*sin(T*t)+6*sin(T*2*t),hx=166-6*sin(T*t),hy=150+5*cos(2*f)
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=BG;c.fill();c.clip()
|
||||||
|
c.fillStyle=GR;c.fillRect(0,214,256,50);c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.moveTo(0,214);c.lineTo(256,214);c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();for(let k=0;k<5;k++){const x=((k*64-t*3*64*2)%320+320)%320-40;c.moveTo(x,232);c.lineTo(x+26,232)}c.stroke()
|
||||||
|
for(const[o,y,r]of[[0,56,.3],[.5,96,-.4]]){
|
||||||
|
const p=((o-t*2)%1+1)%1,x=280-p*340,a=r+p*6
|
||||||
|
c.save();c.translate(x,y+10*sin(T*(p*2+o)));c.rotate(a);c.lineWidth=4;c.strokeStyle='#111'
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.roundRect(-15,-16,30,32,4);c.fill();c.stroke()
|
||||||
|
c.fillStyle=RED;c.beginPath();c.roundRect(-15,-16,30,10,[4,4,0,0]);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(-6,0);c.lineTo(6,0);c.moveTo(-6,8);c.lineTo(6,8);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
const leg=(p,col)=>{const a=.75*sin(p),b=.15+1.5*max(0,cos(p+PI/4))**1.5;limb(c,hx,hy,a,30,a-b,30,col,12);const kx=hx+30*sin(a),ky=hy+30*cos(a),fx=kx+30*sin(a-b),fy=ky+30*cos(a-b);c.save();c.translate(fx,fy);c.rotate(-(a-b)+.1);c.fillStyle='#212529';c.lineWidth=4;c.strokeStyle='#111';c.beginPath();c.ellipse(6,0,12,7,0,0,T);c.fill();c.stroke();c.restore()}
|
||||||
|
const sx=hx+16,sy=hy-44,arm=(p,col)=>{const u=-.9*sin(p);const[x,y]=limb(c,sx,sy,u,24,u+1.7,20,col,11);c.fillStyle=SKIN;c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.arc(x,y,8,0,T);c.fill();c.stroke()}
|
||||||
|
leg(f+PI,'#343a40');arm(f+PI,'#1c7ed6')
|
||||||
|
for(const[w,col]of[[44,'#111'],[34,SH]])c.lineWidth=w,c.strokeStyle=col,c.beginPath(),c.moveTo(hx,hy-6),c.lineTo(sx,sy),c.stroke()
|
||||||
|
leg(f,PA)
|
||||||
|
const tx=sx+10,ty=sy-30
|
||||||
|
c.save();c.translate(tx,ty);c.rotate(.15)
|
||||||
|
c.lineWidth=6;c.strokeStyle='#111';c.fillStyle=SKIN;c.beginPath();c.arc(0,0,27,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HAIR;c.beginPath();c.moveTo(-27,-2);c.quadraticCurveTo(-30,-30,0,-28);c.quadraticCurveTo(22,-28,26,-12);c.quadraticCurveTo(6,-18,-6,-12);c.quadraticCurveTo(-14,-6,-27,-2);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(12,-2,9,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.arc(15,-2,3.5,0,T);c.fill()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(4,-16);c.lineTo(20,-12);c.stroke()
|
||||||
|
c.fillStyle='#c92a2a';c.beginPath();c.ellipse(17,15,6,7+2*sin(f*2),0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ff8fa3';c.beginPath();c.ellipse(0,10,6,4,0,0,T);c.fill()
|
||||||
|
c.restore()
|
||||||
|
arm(f,SH)
|
||||||
|
c.fillStyle='#74c0fc';c.strokeStyle='#111';c.lineWidth=3
|
||||||
|
for(let k=0;k<2;k++){const p=(t*3+k/2)%1,x=tx-20-p*44,y=ty-24-20*sin(PI*p)+p*30;if(p<.8)c.beginPath(),c.moveTo(x,y-7),c.quadraticCurveTo(x+6,y+2,x,y+5),c.quadraticCurveTo(x-6,y+2,x,y-7),c.fill(),c.stroke()}
|
||||||
|
c.save();c.translate(bx,0)
|
||||||
|
c.fillStyle='#111';c.beginPath();c.moveTo(-26,0);for(let y=0;y<=256;y+=16)c.lineTo(26+(y/16)%2*8-4,y);c.lineTo(-300,256);c.lineTo(-300,0);c.fill()
|
||||||
|
c.fillStyle=RED;c.beginPath();c.moveTo(-20,0);for(let y=0;y<=256;y+=16)c.lineTo(20+(y/16)%2*8-4,y);for(let y=256;y>=0;y-=16)c.lineTo(-20+(y/16+1)%2*8-4,y);c.fill()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=4.5;c.lineCap='round';[...'DEADLINE'].forEach((ch,k)=>{glyph(c,ch,-7,22+k*27,3.4);c.stroke()})
|
||||||
|
c.restore()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;for(const k of[0,1,2]){const y=70+k*50+6*sin(T*(t*3+k*.3)),x=bx+34+4*sin(T*(t*6+k*.5));c.beginPath();c.moveTo(x,y);c.lineTo(x+12+6*sin(T*(t*6+k)),y);c.stroke()}
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// 3am doomscroll: wide awake eyes peek over the blanket, lit by the phone, flicking post after post while the bedside clock races on
|
||||||
|
const{cos,sin,PI}=Math,T=2*PI
|
||||||
|
export const frames=16,delay=Array(16).fill(95),rim=4
|
||||||
|
const K='#1b1b1f',GL=['#74c0fc','#f783ac','#8ce99a','#ffd43b'],FC=['#d0ebff','#ffdeeb','#d3f9d8','#fff3bf']
|
||||||
|
const SEG=[63,6,91,79,102,109,125,7,127,111]
|
||||||
|
const digit=(c,x,y,n,s)=>{c.beginPath();[[0,0,1,0],[1,0,1,1],[1,1,1,2],[0,2,1,2],[0,1,0,2],[0,0,0,1],[0,1,1,1]].forEach(([a,b,e,f],k)=>{if(SEG[n]>>k&1)c.moveTo(x+a*s,y+b*s),c.lineTo(x+e*s,y+f*s)});c.stroke()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const f=i>>2,p=i%4,col=GL[f],jerk=p==0?-5:0,up=[16,8,3,0][p]
|
||||||
|
c.strokeStyle=K;c.lineWidth=6
|
||||||
|
c.fillStyle='#1c2541';c.beginPath();c.roundRect(14,14,228,228,28);c.fill();c.stroke()
|
||||||
|
c.save();c.clip()
|
||||||
|
// window with moon, clock
|
||||||
|
c.fillStyle='#3a506b';c.lineWidth=5;c.beginPath();c.roundRect(32,32,72,68,8);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ffe066';c.beginPath();c.arc(78,58,15,0,T);c.fill();c.fillStyle='#3a506b';c.beginPath();c.arc(70,52,13,0,T);c.fill()
|
||||||
|
c.fillStyle='#fff';for(const[x,y]of[[46,46],[54,82],[90,86]])c.fillRect(x-1.5,y-1.5,3,3)
|
||||||
|
c.strokeStyle=K;c.beginPath();c.moveTo(68,32);c.lineTo(68,100);c.moveTo(32,66);c.lineTo(104,66);c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.roundRect(140,34,86,44,9);c.fill();c.stroke()
|
||||||
|
const mm=[7,24,41,58][f];c.strokeStyle='#ff6b6b';c.lineWidth=4;c.lineCap='round'
|
||||||
|
digit(c,154,44,3,12);digit(c,184,44,mm/10|0,12);digit(c,204,44,mm%10,12)
|
||||||
|
c.fillStyle='#ff6b6b';if(p<2)for(const y of[51,63])c.beginPath(),c.arc(174,y,2.5,0,T),c.fill()
|
||||||
|
// pillow, head lit by the screen
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle='#5c6b8a';c.beginPath();c.roundRect(46,112,164,70,30);c.fill();c.stroke()
|
||||||
|
const g=c.createRadialGradient(128,176,10,128,176,110);g.addColorStop(0,col+'aa');g.addColorStop(1,col+'00');c.fillStyle=g;c.fillRect(14,60,228,180)
|
||||||
|
c.fillStyle=FC[f];c.beginPath();c.arc(128,158,50,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#5c3d2e';c.beginPath();c.moveTo(80,150);c.quadraticCurveTo(80,104,128,106);c.quadraticCurveTo(178,104,177,150);c.quadraticCurveTo(160,126,140,128);c.lineTo(146,114);c.lineTo(126,128);c.quadraticCurveTo(98,126,80,150);c.fill();c.stroke()
|
||||||
|
for(const d of[-1,1]){const x=128+d*21,y=154
|
||||||
|
c.strokeStyle='#9775fa';c.lineWidth=4;c.beginPath();c.arc(x,y+4,17,PI*.2,PI*.8);c.stroke();c.beginPath();c.arc(x,y+9,14,PI*.3,PI*.7);c.stroke()
|
||||||
|
c.fillStyle='#fff';c.strokeStyle=K;c.lineWidth=4;c.beginPath();c.arc(x,y,15,0,T);c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#ff8787';c.lineWidth=2;for(const a of[2.6,.5,3.4])c.beginPath(),c.moveTo(x+14*cos(a),y+14*sin(a)),c.lineTo(x+8*cos(a+.2),y+8*sin(a+.2)),c.stroke()
|
||||||
|
c.fillStyle=K;c.beginPath();c.arc(x,y+4-up*.5,5,0,T);c.fill();c.fillStyle=col;c.fillRect(x+1,y-1-up*.5,4,3)}
|
||||||
|
// blanket and phone
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle='#7048e8';c.beginPath();c.moveTo(10,190);c.quadraticCurveTo(128,170,250,190);c.lineTo(250,250);c.lineTo(10,250);c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#845ef7';c.lineWidth=5;for(const x of[50,206])c.beginPath(),c.moveTo(x,196),c.quadraticCurveTo(x+6,220,x-4,244),c.stroke()
|
||||||
|
c.restore()
|
||||||
|
c.save();c.translate(0,jerk);c.strokeStyle=K;c.lineWidth=6
|
||||||
|
c.fillStyle='#343a40';c.beginPath();c.roundRect(100,176,56,62,10);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#495057';c.beginPath();c.roundRect(110,184,16,16,5);c.fill()
|
||||||
|
c.fillStyle=col;c.fillRect(108,173,40,3)
|
||||||
|
c.fillStyle=FC[f];c.lineWidth=5;for(const x of[98,158])c.beginPath(),c.ellipse(x,212,11,14,0,0,T),c.fill(),c.stroke()
|
||||||
|
c.restore()
|
||||||
|
if(p==0){c.strokeStyle='#fff';c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*38,172),c.lineTo(128+d*48,164),c.stroke()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// little blob sunk into a red cinema seat shoveling popcorn nonstop, eyes darting side to side following the drama
|
||||||
|
const{sin,cos,PI,max,min,abs,floor}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=70,rim=5
|
||||||
|
const Y='#ffd43b',BL='#ff8787',SR='#e03131',SD='#a61e4d',SC='#ff6b6b',PC='#fff3bf',PB='#fa5252'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const pop=(c,x,y,s=1)=>{c.lineWidth=3.5;c.fillStyle=PC;c.beginPath();for(const[a,b,r]of[[-4,1,5],[4,1,5],[0,-4,5.5]])c.moveTo(x+a*s+r*s,y+b*s),c.arc(x+a*s,y+b*s,r*s,0,T);c.stroke();c.fill()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
// two scoops per loop: dip (0-.2), up to mouth (.2-.35), chew; eyes snap left/right each quarter
|
||||||
|
const u=(t*2)%1,toM=ez(u,.18,.36)-ez(u,.62,.9),chew=u>.36&&u<.7?abs(sin((u-.36)*T*3)):0
|
||||||
|
const ph=floor(t*4),snap=ez((t*4)%1,0,.12),look=(ph%2?-1:1)*(2*snap-1)*-1
|
||||||
|
// seat
|
||||||
|
c.fillStyle=SR;c.beginPath();c.roundRect(34,14,188,210,[60,60,14,14]);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SC;c.lineWidth=5;c.beginPath();c.roundRect(52,30,152,180,[46,46,10,10]);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(128,36);c.lineTo(128,90);c.stroke()
|
||||||
|
// blob body
|
||||||
|
c.lineWidth=7;c.fillStyle=Y;c.beginPath();c.moveTo(56,236);c.bezierCurveTo(50,120,74,70,128,70);c.bezierCurveTo(182,70,206,120,200,236);c.closePath();c.fill();c.stroke()
|
||||||
|
// armrests + seat front
|
||||||
|
c.fillStyle=SD;for(const x of[14,206])c.beginPath(),c.roundRect(x,170,36,70,10),c.fill(),c.stroke()
|
||||||
|
// face
|
||||||
|
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*44,138+chew*2,11,6,0,0,T),c.fill()
|
||||||
|
for(const d of[-1,1]){const x=128+d*24,y=112
|
||||||
|
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.ellipse(x,y,15,17,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.arc(x+look*7,y+2,7,0,T);c.fill()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.arc(x+look*7+2.5,y-1,2.2,0,T);c.fill()
|
||||||
|
c.lineWidth=5;c.beginPath();c.arc(x,y-4,24,-PI/2-.45-d*.12,-PI/2+.45-d*.12);c.stroke()}
|
||||||
|
const mo=toM>.85?1:0
|
||||||
|
c.fillStyle='#c92a2a';c.lineWidth=4.5
|
||||||
|
if(mo)c.beginPath(),c.ellipse(128,148,12,11,0,0,T),c.fill(),c.stroke()
|
||||||
|
else{c.beginPath();c.ellipse(128,148,9+chew*3,5+chew*4,0,0,T);c.fill();c.stroke()}
|
||||||
|
// soda in the cup holder, other hand resting
|
||||||
|
c.lineWidth=6;c.fillStyle='#fff';c.beginPath();c.moveTo(16,134);c.lineTo(48,134);c.lineTo(44,176);c.lineTo(20,176);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#4dabf7';c.beginPath();c.moveTo(18,150);c.lineTo(46,150);c.lineTo(44.5,166);c.lineTo(19.5,166);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#e9ecef';c.beginPath();c.roundRect(12,126,40,10,5);c.fill();c.stroke()
|
||||||
|
for(const[w,s]of[[12,'#111'],[5,'#ff6b6b']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(34,128),c.lineTo(40,104),c.lineTo(50,98),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=7;c.fillStyle=Y;c.beginPath();c.ellipse(64,184,16,14,-.3,0,T);c.fill();c.stroke()
|
||||||
|
// bucket
|
||||||
|
const bx=172,by=196
|
||||||
|
c.save();c.beginPath();c.moveTo(bx-34,by-40);c.lineTo(bx+34,by-40);c.lineTo(bx+24,by+46);c.lineTo(bx-24,by+46);c.closePath();c.fillStyle='#fff';c.fill();c.clip()
|
||||||
|
c.fillStyle=PB;for(let k=-3;k<4;k+=2){c.beginPath();c.moveTo(bx+k*10,by-40);c.lineTo(bx+(k+1)*10,by-40);c.lineTo(bx+(k+1)*7,by+46);c.lineTo(bx+k*7,by+46);c.fill()}
|
||||||
|
c.restore();c.lineWidth=6;c.beginPath();c.moveTo(bx-34,by-40);c.lineTo(bx+34,by-40);c.lineTo(bx+24,by+46);c.lineTo(bx-24,by+46);c.closePath();c.stroke()
|
||||||
|
for(const[x,y]of[[-24,-44],[-10,-50],[6,-48],[22,-44],[-16,-38],[14,-38],[0,-40],[30,-38]])pop(c,bx+x,by+y,1.2)
|
||||||
|
// flying kernels
|
||||||
|
for(let k=0;k<3;k++){const p=(t*3+k/3)%1,x=bx-20+k*18+p*(k-1)*30,y=by-50-60*p+70*p*p;if(p<.8)pop(c,x,y,.9)}
|
||||||
|
// scooping hand
|
||||||
|
const hx=bx-6+(140-bx+6)*toM,hy=by-46+(158-by+46)*toM-sin(toM*PI)*8
|
||||||
|
c.lineWidth=7;c.fillStyle=Y
|
||||||
|
for(const[w,s]of[[26,'#111'],[13,Y]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(190,170),c.quadraticCurveTo(206,hy-6,hx+10,hy+6),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=7
|
||||||
|
if(toM>.3&&!mo)pop(c,hx-6,hy-10,1)
|
||||||
|
c.beginPath();c.ellipse(hx,hy,17,15,.3,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(hx-8,hy-4);c.lineTo(hx-2,hy-6);c.moveTo(hx-8,hy+4);c.lineTo(hx-2,hy+2);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// deeply unimpressed cat rolls its eyes so hard the pupils spin all the way around twice, then sighs and goes back to the flat stare
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
const U=[0,.15,.2,.25,...Array.from({length:12},(_,k)=>.27+k*.033),.68,.74,.8,.88]
|
||||||
|
export const frames=U.length,delay=[700,70,70,70,...Array(12).fill(45),80,90,110,600],rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u*u*(3-2*u))
|
||||||
|
const K='#1b1b1f',O='#ffa94d',OD='#f76707',M='#fff4e6'
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=U[i],tilt=io((t-.13)/.12)*(1-io((t-.68)/.12)),sp=cl((t-.25)/.42),th=-PI/2+2*T*(sp<.5?2*sp*sp:1-2*(1-sp)**2)
|
||||||
|
const look=io((t-.13)/.12)*(1-io((t-.68)/.12)),lid=.5-.42*look,spin=t>.26&&t<.68
|
||||||
|
c.save();c.translate(128,226);c.rotate(-.1*tilt);c.translate(-128,-226-8*tilt)
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.lineJoin='round'
|
||||||
|
for(const d of[-1,1]){c.fillStyle=O;c.beginPath();c.moveTo(128+d*86,110);c.lineTo(128+d*70,22);c.lineTo(128+d*24,72);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ffc9c9';c.beginPath();c.moveTo(128+d*74,88);c.lineTo(128+d*67,40);c.lineTo(128+d*42,68);c.fill()}
|
||||||
|
c.fillStyle=O;c.beginPath();c.ellipse(128,146,96,80,0,0,T);c.fill();c.stroke()
|
||||||
|
c.strokeStyle=OD;c.lineWidth=7;for(const d of[-18,0,18])c.beginPath(),c.moveTo(128+d,70),c.lineTo(128+d*.7,92),c.stroke()
|
||||||
|
for(const d of[-1,1])for(const y of[132,152])c.beginPath(),c.moveTo(128+d*94,y),c.lineTo(128+d*76,y+4),c.stroke()
|
||||||
|
c.strokeStyle=K;c.lineWidth=6
|
||||||
|
c.fillStyle=M;c.beginPath();c.ellipse(128,186,46,30,0,0,T);c.fill()
|
||||||
|
for(const d of[-1,1]){const x=128+d*38,y=136
|
||||||
|
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.ellipse(x,y,26,24,0,0,T);c.fill()
|
||||||
|
c.save();c.clip()
|
||||||
|
const pr=spin?15:look>.5?15*look:0,px=x+pr*cos(spin?th:-PI/2)+(look<.5?d*-2:0),py=y+pr*sin(spin?th:-PI/2)+(look<.5?6*(1-look):0)
|
||||||
|
if(spin){c.strokeStyle='#adb5bd';c.lineWidth=6;c.beginPath();c.arc(x,y,15,th-1.6,th-.3);c.stroke();c.strokeStyle=K}
|
||||||
|
c.fillStyle=K;c.beginPath();c.arc(px,py,10,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(px+3,py-3,3,0,T);c.fill()
|
||||||
|
c.fillStyle=O;c.fillRect(x-30,y-28,60,52*lid);c.restore()
|
||||||
|
c.lineWidth=5;c.beginPath();c.ellipse(x,y,26,24,0,0,T);c.stroke()
|
||||||
|
c.beginPath();c.moveTo(x-27,y-24+48*lid);c.lineTo(x+27,y-24+48*lid);c.stroke()}
|
||||||
|
c.fillStyle='#f783ac';c.lineWidth=4;c.beginPath();c.moveTo(118,170);c.lineTo(138,170);c.lineTo(128,180);c.closePath();c.fill();c.stroke()
|
||||||
|
c.beginPath();c.moveTo(128,180);c.lineTo(128,188);c.moveTo(114,196);c.quadraticCurveTo(128,192,142,196);c.stroke()
|
||||||
|
c.lineWidth=3;for(const d of[-1,1])for(const a of[-.12,.08])c.beginPath(),c.moveTo(128+d*50,184+a*30),c.lineTo(128+d*84,180+a*120),c.stroke()
|
||||||
|
c.restore()
|
||||||
|
const pf=cl((t-.72)/.14)
|
||||||
|
if(pf>0&&pf<1){c.fillStyle='#fff';c.strokeStyle=K;c.lineWidth=4;for(const[k,r]of[[0,10],[1,14],[2,11]]){const s=(1-pf)*1.6;c.beginPath();c.arc(156+34*pf+k*17,204+12*pf+(k%2?-7:5),r*s+4,0,T);c.fill();c.stroke()}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// deadpan blob slowly raises a hand, plants it on its face with a smack, holds it there, then drags it down its face in despair
|
||||||
|
const{sin,cos,PI,max,min}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=80,rim=5
|
||||||
|
const Y='#ffd43b',BL='#ff8787',YD='#f0b400'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const hand=(c,x,y,a)=>{c.save();c.translate(x,y);c.rotate(a);c.scale(1.4,1.4);c.fillStyle=Y;c.lineWidth=5
|
||||||
|
for(const[fx,h]of[[-24,30],[-8,36],[8,36],[24,30]])c.beginPath(),c.roundRect(fx-8,-h-14,16,h+20,8),c.fill(),c.stroke()
|
||||||
|
c.beginPath();c.ellipse(36,6,10,18,-.7,0,T);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(-34,-20,68,52,[10,10,22,22]);c.fill();c.stroke()
|
||||||
|
c.fillStyle=Y;c.fillRect(-29,-24,58,8)
|
||||||
|
c.strokeStyle=YD;c.lineWidth=3;c.beginPath();for(const fx of[-16,0,16])c.moveTo(fx,-22),c.lineTo(fx,-14);c.stroke();c.strokeStyle='#111'
|
||||||
|
c.restore()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const raise=ez(t,.16,.34),slap=ez(t,.34,.38),drag=ez(t,.62,.84),drop=ez(t,.84,.98),hit=t>=.38&&t<.5
|
||||||
|
const sq=hit?1-.05*(1-ez(t,.38,.48)):1,shake=t>=.46&&t<.62?.035*sin((t-.46)*T*6):0
|
||||||
|
// body
|
||||||
|
c.save();c.translate(128,240);c.scale(2-sq,sq);c.rotate(shake);c.translate(-128,-240)
|
||||||
|
c.fillStyle=Y;c.beginPath();c.moveTo(48,240);c.bezierCurveTo(42,130,72,72,128,72);c.bezierCurveTo(184,72,214,130,208,240);c.closePath();c.fill();c.stroke()
|
||||||
|
// face: flat stare, eyes and mouth pulled down while the hand drags
|
||||||
|
const pl=drag*(1-drop)*14,bl=t>=.08&&t<.12
|
||||||
|
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*46,158+pl*.6,11,5,0,0,T),c.fill()
|
||||||
|
for(const d of[-1,1]){const x=128+d*26,y=128
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4.5;c.beginPath();c.ellipse(x,y+pl*.5,13,10+pl*.5,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';if(!bl)c.beginPath(),c.arc(x,y+3+pl*.6,5,0,T),c.fill()
|
||||||
|
c.fillStyle=Y;c.beginPath();c.rect(x-15,y-14,30,12+(bl?14:0));c.fill()
|
||||||
|
c.lineWidth=5.5;c.beginPath();c.moveTo(x-15,y-2+(bl?12:0));c.lineTo(x+15,y-2+(bl?12:0));c.stroke()}
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(112,172+pl);c.quadraticCurveTo(128,170+pl*1.5,144,172+pl);c.stroke()
|
||||||
|
// the hand: up from the side, smack onto the face, drag down, drop
|
||||||
|
const hx=206-76*raise+76*drop,hy=250-120*raise+14*slap+72*drag+50*drop,ha=.45-.45*raise+.4*drop,wx=hx-sin(ha)*44,wy=hy+cos(ha)*44
|
||||||
|
for(const[w,s]of[[30,'#111'],[16,Y]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(214,250),c.quadraticCurveTo(212,wy+10,wx,wy),c.stroke()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
hand(c,hx,hy,ha)
|
||||||
|
c.restore()
|
||||||
|
if(hit){const p=ez(t,.38,.44);for(const d of[-1,1])for(let k=0;k<3;k++){const a=(d>0?0:PI)+(k-1)*.5;for(const[w,s]of[[10,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(128+cos(a)*(64+10*p),116+sin(a)*(44+8*p)),c.lineTo(128+cos(a)*(84+16*p),116+sin(a)*(58+12*p)),c.stroke()}c.strokeStyle='#111'}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// a calm paper plate smiley held over a face, it slips for a second and shows the frantic scream underneath, then gets slapped back up: I'M FINE
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
export const frames=28,delay=85,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)}
|
||||||
|
const G={I:'0040 202c 0c4c',"'":'0003',M:'0c0056a0ac'," ":'',F:'80000c 0666',N:'0c008c80',E:'80000c8c 0666'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const SK='#ffd8a8',HX=188,HY=112
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const slip=ez(t,.3,.38)-ez(t,.62,.68),scr=slip>.3
|
||||||
|
// shirt and shoulders
|
||||||
|
c.fillStyle='#38d9a9';c.lineWidth=7;c.beginPath();c.moveTo(36,256);c.quadraticCurveTo(40,186,128,180);c.quadraticCurveTo(216,186,220,256);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SK;c.beginPath();c.moveTo(106,170);c.lineTo(106,188);c.quadraticCurveTo(128,200,150,188);c.lineTo(150,170);c.fill();c.lineWidth=6;c.beginPath();c.moveTo(106,172);c.lineTo(106,186);c.moveTo(150,172);c.lineTo(150,186);c.stroke()
|
||||||
|
// head, the face underneath screams
|
||||||
|
c.save()
|
||||||
|
c.fillStyle='#5c3d2e';c.lineWidth=7;c.beginPath();c.moveTo(60,104);for(let k=0;k<=8;k++){const a=PI+k*PI/8,r=k%2?(scr?96:84):70;c.lineTo(128+r*cos(a+(k%2?0:0)),108+r*sin(a))}c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=SK;c.beginPath();c.arc(128,110,66,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#5c3d2e';c.beginPath();c.moveTo(64,100);c.quadraticCurveTo(80,44,128,44);c.quadraticCurveTo(176,44,192,100);c.quadraticCurveTo(170,74,150,80);c.lineTo(140,66);c.lineTo(124,80);c.lineTo(110,66);c.lineTo(98,82);c.quadraticCurveTo(76,78,64,100);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.arc(128+d*26,102,15,0,T),c.fill(),c.stroke()
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*26+(i%2?1.5:-1.5),102,3.5,0,T),c.fill()
|
||||||
|
c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*12,72),c.lineTo(128+d*40,80),c.stroke()
|
||||||
|
c.fillStyle='#862e2e';c.beginPath();c.ellipse(128,144,20,23,0,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.clip();c.fillStyle='#fff';c.fillRect(100,118,56,10);c.fillStyle='#ff8787';c.beginPath();c.ellipse(128,166,14,9,0,0,T);c.fill();c.restore()
|
||||||
|
c.lineWidth=5;c.beginPath();c.ellipse(128,144,20,23,0,0,T);c.stroke()
|
||||||
|
c.fillStyle='#74c0fc';c.lineWidth=3.5;for(const[x,y]of[[68,84],[192,128]])c.beginPath(),c.moveTo(x,y-11),c.quadraticCurveTo(x+7,y,x+7,y+3),c.arc(x,y+3,7,0,PI),c.quadraticCurveTo(x-7,y,x,y-11),c.fill(),c.stroke()
|
||||||
|
c.restore()
|
||||||
|
if(scr){c.lineWidth=5;for(const[a,r]of[[-2.6,84],[-2.1,92],[-1.05,92],[-.55,84],[-3,80],[-.1,80]]){const r2=r+(i%2?16:12);c.beginPath();c.moveTo(128+r*cos(a),110+r*sin(a));c.lineTo(128+r2*cos(a),110+r2*sin(a));c.stroke()}}
|
||||||
|
// the mask, held at its right edge, swings down when it slips
|
||||||
|
const hy=HY+48*slip,hx=HX+10*slip
|
||||||
|
c.save();c.translate(hx,hy);c.rotate(-1.45*slip);c.translate(-62,0)
|
||||||
|
c.fillStyle='#f1f3f5';c.lineWidth=6;c.beginPath();c.arc(0,0,68,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=3;c.beginPath();c.arc(0,0,54,0,T);c.fill();c.strokeStyle='#ced4da';c.stroke();c.strokeStyle='#111'
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(d*20,-12,5,7,0,0,T),c.fill()
|
||||||
|
c.fillStyle='#ffc9c9';for(const d of[-1,1])c.beginPath(),c.ellipse(d*33,8,8,5,0,0,T),c.fill()
|
||||||
|
c.lineWidth=5;c.beginPath();c.arc(0,4,24,.2*PI,.8*PI);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// arm and the gripping hand
|
||||||
|
c.lineCap='round';for(const[w,s]of[[26,'#111'],[14,'#38d9a9']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(214,256),c.quadraticCurveTo(226,200,hx+6,hy+20),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.fillStyle=SK;c.lineWidth=5;c.beginPath();c.roundRect(hx-10,hy-14,26,32,10);c.fill();c.stroke()
|
||||||
|
c.lineWidth=3;for(const y of[-4,4])c.beginPath(),c.moveTo(hx-10,hy+y),c.lineTo(hx,hy+y),c.stroke()
|
||||||
|
txt(c,"I'M FINE",128,232,22,'#fff')
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// a phone sends "hey :)", it gets marked read, then the contact's little avatar turns into a ghost that floats up out of the phone, waves bye and drifts away
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=32,delay=90,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)},pop=u=>(u=cl(u),u<.6?1.2*u/.6:1.2-.2*(u-.6)/.4)
|
||||||
|
const G={H:'000c 808c 0686',E:'80000c8c 0666',Y:'004680 464c'," ":'',":":'0404 0a0a',")":'00222a0c',R:'0c006082856707 478c',A:'0c0440848c 0787',D:'005083895c0c00'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){if(!s)continue;c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const ghost=(c,x,y,s,t,wave)=>{
|
||||||
|
c.save();c.translate(x,y);c.scale(s,s);c.lineWidth=5;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||||
|
for(const d of[-1,1]){c.save();c.translate(d*22,8);c.scale(d,1);c.rotate(d>0?-.2-wave:.7);c.beginPath();c.moveTo(0,-6);c.quadraticCurveTo(9,-8,13,-16);c.arc(17,-13,5.5,PI*1.2,PI*.25);c.quadraticCurveTo(14,4,0,9);c.fill();c.stroke();c.restore()}
|
||||||
|
c.beginPath();c.moveTo(-26,30);c.lineTo(-26,0);c.arc(0,0,26,PI,0);c.lineTo(26,30)
|
||||||
|
for(let k=0;k<3;k++){const a=26-k*52/3,b=a-52/3;c.quadraticCurveTo((a+b)/2,30+14+5*sin(t*T*2+k*2),b,30)}
|
||||||
|
c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(d*9,-2,4,6,0,0,T),c.fill()
|
||||||
|
c.fillStyle='#ffa8a8';for(const d of[-1,1])c.beginPath(),c.ellipse(d*16,8,5,3,0,0,T),c.fill()
|
||||||
|
c.lineWidth=3.5;c.beginPath();c.arc(0,8,5,.15*PI,.85*PI);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t)=>{
|
||||||
|
const msg=pop((t-.04)/.08)*(1-ez(t,.9,.96)),rd=ez(t,.16,.2)*(1-ez(t,.9,.95)),out=ez(t,.36,.5),back=ez(t,.94,1)
|
||||||
|
const shake=t>.26&&t<.36?2.5*sin(t*T*24):0
|
||||||
|
// phone
|
||||||
|
c.fillStyle='#845ef7';c.lineWidth=7;c.beginPath();c.roundRect(56,78,144,174,24);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#f8f9fa';c.lineWidth=4;c.beginPath();c.roundRect(67,90,122,150,13);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.roundRect(110,94,36,8,4);c.fill()
|
||||||
|
c.strokeStyle='#dee2e6';c.lineWidth=3;c.beginPath();c.moveTo(69,136);c.lineTo(187,136);c.stroke()
|
||||||
|
c.strokeStyle='#adb5bd';c.lineWidth=7;c.beginPath();c.moveTo(114,119);c.lineTo(164,119);c.stroke()
|
||||||
|
// avatar slot, the contact is there until they ghost
|
||||||
|
const ax=92+shake,ay=119
|
||||||
|
if(out<.05||back>.05){const s=back>.05?pop(back):1;c.save();c.translate(ax,ay);c.scale(s*1.25,s*1.25);c.fillStyle='#ffd43b';c.strokeStyle='#111';c.lineWidth=3.5;c.beginPath();c.arc(0,0,11,0,T);c.fill();c.stroke();c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*4,-1,1.8,0,T),c.fill();c.lineWidth=2;c.beginPath();c.arc(0,2,4,.2*PI,.8*PI);c.stroke();c.restore()}
|
||||||
|
else{c.strokeStyle='#adb5bd';c.lineWidth=3;c.setLineDash([4,4]);c.beginPath();c.arc(92,119,14,0,T);c.stroke();c.setLineDash([])}
|
||||||
|
// the message
|
||||||
|
if(msg>0){c.save();c.beginPath();c.roundRect(67,90,122,150,13);c.clip();c.translate(178,184);c.scale(msg*1.2,msg*1.2)
|
||||||
|
c.fillStyle='#4dabf7';c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.moveTo(-4,-14);c.lineTo(-4,10);c.quadraticCurveTo(-4,16,6,18);c.quadraticCurveTo(-4,20,-12,14);c.lineTo(-74,14);c.quadraticCurveTo(-82,14,-82,6);c.lineTo(-82,-14);c.quadraticCurveTo(-82,-22,-74,-22);c.lineTo(-12,-22);c.quadraticCurveTo(-4,-22,-4,-14);c.fill();c.stroke()
|
||||||
|
txt(c,'HEY :)',-43,-4,14,'#fff','#1864ab');c.restore()}
|
||||||
|
if(rd>0){c.save();c.globalAlpha=1;c.translate(160,224);c.scale(rd,rd);txt(c,'READ',0,0,10,'#868e96',null);c.restore()}
|
||||||
|
// the ghost leaving
|
||||||
|
if(out>.05&&back<.05){const u=ez(t,.36,.52)
|
||||||
|
,lv=ez(t,.72,.92),gx=ax+(128-ax)*u+10*sin(t*T*2),gy=ay+(42-ay)*u-180*lv*lv,s=.45+.6*u,wave=t>.48&&t<.82?.5*sin(t*T*6):0
|
||||||
|
ghost(c,gx,gy,s,t,wave)}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// a smug takeout box smoulders, then flips its lid open and a huge flame roars out of it: HOT TAKE
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=90,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)},bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||||
|
const G={H:'000c 808c 0686',O:'2060828a6c2c0a0220',T:'0080 404c'," ":'',A:'0c0440848c 0787',K:'000c 8007 358c',E:'80000c8c 0666'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
// cartoon flame with three curling tongues standing on (x,y), w wide and h tall
|
||||||
|
const flame=(c,x,y,w,h,t,col,lw)=>{
|
||||||
|
const f=k=>sin(t*T*2+k),a=w*.06*f(0),b=w*.05*f(2),d=w*.05*f(4),hc=h*(.92+.08*sin(t*T*3)),hs=h*(.62+.06*f(1))
|
||||||
|
c.save();c.translate(x,y);c.beginPath();c.moveTo(-w/2,0)
|
||||||
|
c.bezierCurveTo(-w*.56,-h*.25,-w*.6,-hs*.8,-w*.5+b,-hs);c.bezierCurveTo(-w*.34,-hs*.8,-w*.24,-hs*.72,-w*.2,-h*.5)
|
||||||
|
c.bezierCurveTo(-w*.28,-hc*.78,-w*.08,-hc*.9,a,-hc);c.bezierCurveTo(w*.16,-hc*.84,w*.26,-hc*.7,w*.2,-h*.5)
|
||||||
|
c.bezierCurveTo(w*.26,-hs*.72,w*.36,-hs*.8,w*.5+d,-hs);c.bezierCurveTo(w*.6,-hs*.8,w*.56,-h*.25,w/2,0)
|
||||||
|
c.bezierCurveTo(w*.46,w*.32,-w*.46,w*.32,-w/2,0);c.closePath()
|
||||||
|
c.fillStyle=col;c.fill();if(lw)c.lineWidth=lw,c.strokeStyle='#111',c.stroke();c.restore()}
|
||||||
|
const BX=128,TOP=124,BOT=204
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const op=bk((t-.26)/.08)-ez(t,.8,.92),fire=ez(t,.26,.32)*(1-ez(t,.78,.9)),hop=t>.26&&t<.4?-14*sin(PI*(t-.26)/.14):0
|
||||||
|
c.save();c.translate(0,hop)
|
||||||
|
// fire behind the front of the box, shooting out of the top
|
||||||
|
const fh=30+100*fire,fw=96+40*fire
|
||||||
|
if(op>.05||fire>0){flame(c,BX,TOP+10,fw,fh,t,'#ff6b6b',6);flame(c,BX,TOP+12,fw*.74,fh*.76,t+.15,'#ff922b',0);flame(c,BX,TOP+14,fw*.46,fh*.5,t+.3,'#ffd43b',0)}
|
||||||
|
else{for(const[d,o]of[[-1,0],[1,.5]]){const u=(t*3+o)%1;c.save();c.translate(BX+d*22+6*sin(u*T),TOP-14-36*u);c.scale(1-u*.5,1-u*.5);c.fillStyle='#dee2e6';c.strokeStyle='#111';c.lineWidth=3.5;c.beginPath();c.arc(0,0,9,0,T);c.fill();c.stroke();c.restore()}}
|
||||||
|
// wire handle
|
||||||
|
c.lineWidth=9;c.strokeStyle='#111';c.beginPath();c.moveTo(70,TOP+4);c.quadraticCurveTo(BX,TOP-118,186,TOP+4);c.stroke();c.lineWidth=4;c.strokeStyle='#ced4da';c.stroke()
|
||||||
|
// lid flaps, hinged at the top corners, swing outward when it opens
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
for(const d of[-1,1]){c.save();c.translate(BX+d*62,TOP);c.rotate(d*1.9*op);c.fillStyle='#f1f3f5';c.lineWidth=6;c.beginPath();c.moveTo(0,0);c.lineTo(-d*62,0);c.lineTo(-d*60,-26);c.lineTo(-d*10,-18);c.closePath();c.fill();c.stroke();c.restore()}
|
||||||
|
// box
|
||||||
|
c.fillStyle='#fff';c.lineWidth=7;c.beginPath();c.moveTo(BX-64,TOP);c.lineTo(BX+64,TOP);c.lineTo(BX+46,BOT);c.lineTo(BX-46,BOT);c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#e03131';c.lineWidth=5;c.beginPath();c.moveTo(BX-60,TOP+14);c.lineTo(BX+60,TOP+14);c.moveTo(BX-50,BOT-14);c.lineTo(BX+50,BOT-14);c.stroke()
|
||||||
|
// smug face
|
||||||
|
c.strokeStyle='#111';const by=(i>>2)%2?-3:0
|
||||||
|
for(const d of[-1,1]){const x=BX+d*22,y=TOP+42
|
||||||
|
c.fillStyle='#111';c.beginPath();c.arc(x+3,y+2,5.5,0,PI);c.fill()
|
||||||
|
c.lineWidth=4.5;c.beginPath();c.moveTo(x-10,y);c.lineTo(x+10,y);c.stroke()
|
||||||
|
c.lineWidth=4.5;c.beginPath();c.moveTo(x-10,y-12+(d>0?by:0)-(d>0?3:0));c.quadraticCurveTo(x,y-17+(d>0?by:0)-(d>0?3:0),x+10,y-12+(d>0?by:0));c.stroke()}
|
||||||
|
c.fillStyle='#ffa8a8';for(const d of[-1,1])c.beginPath(),c.ellipse(BX+d*36,TOP+56,7,4,0,0,T),c.fill()
|
||||||
|
c.lineWidth=4.5;c.beginPath();c.moveTo(BX-14,TOP+60);c.quadraticCurveTo(BX+4,TOP+68,BX+18,TOP+55);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
txt(c,'HOT TAKE',BX,236,22,'#fff')
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// lightbulb gets a brilliant idea and blazes on with a "!", then flickers, fizzles out with a puff of smoke and is left with a blank "?"
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=[...Array(23).fill(90),700],rim=4
|
||||||
|
const G={'!':'M2 0L2 3.8M2 5.9L2 6','?':'M.1 1.2Q.6 0 2 0Q4 0 4 1.7Q4 3 2 3.3L2 4M2 5.9L2 6'}
|
||||||
|
const txt=(c,s,x,y,k,col,w)=>{
|
||||||
|
const a=5.4*k,W=s.length*a-1.4*k;c.beginPath()
|
||||||
|
;[...s].forEach((ch,j)=>{const ox=x-W/2+j*a;for(const[,o,q]of(G[ch]||'').matchAll(/([MLQ])([^MLQ]*)/g)){const n=q.trim().split(/[ ,]+/).map((v,m)=>m%2?y+v*k:ox+v*k);o=='M'?c.moveTo(...n):o=='L'?c.lineTo(...n):c.quadraticCurveTo(...n)}})
|
||||||
|
for(const[l,s]of[[w+7,'#111'],[w,col]])c.lineWidth=l,c.strokeStyle=s,c.stroke();c.strokeStyle='#111'
|
||||||
|
}
|
||||||
|
const pop=x=>x<=0?0:x>=1?1:1+sin(PI*x)*.45*(1-x)
|
||||||
|
const X=128,Y=118,R=58
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const ph=i<3?0:i<11?1:i<16?2:3,on=ph==1||ph==2&&[0,1,0,1,0][i-11],tilt=ph==3?-.14*min(1,(i-15)/2):0
|
||||||
|
c.save();c.translate(X,214);c.rotate(tilt);c.translate(-X,-214)
|
||||||
|
// rays
|
||||||
|
if(on){const p=1+.1*(i%2);c.strokeStyle='#111';for(const[w,s]of[[13,'#111'],[6,'#ffd43b']]){c.lineWidth=w;c.strokeStyle=s;for(let k=0;k<9;k++){if(k==4)continue;const a=PI*.86+k*PI*1.28/8,r0=R+12,r1=R+(k%2?24:36)*p;c.beginPath();c.moveTo(X+cos(a)*r0,Y+sin(a)*r0);c.lineTo(X+cos(a)*r1,Y+sin(a)*r1);c.stroke()}}c.strokeStyle='#111'}
|
||||||
|
// screw base
|
||||||
|
c.fillStyle='#adb5bd';c.lineWidth=7;c.beginPath();c.moveTo(96,166);c.lineTo(160,166);c.lineTo(154,206);c.lineTo(102,206);c.closePath();c.fill();c.stroke()
|
||||||
|
c.lineWidth=5;for(const y of[180,194])c.beginPath(),c.moveTo(100,y),c.lineTo(156,y),c.stroke()
|
||||||
|
c.fillStyle='#495057';c.lineWidth=6;c.beginPath();c.moveTo(108,206);c.lineTo(148,206);c.quadraticCurveTo(140,224,128,224);c.quadraticCurveTo(116,224,108,206);c.fill();c.stroke()
|
||||||
|
// glass
|
||||||
|
c.fillStyle=on?'#ffe066':'#e9ecef';c.lineWidth=7;c.beginPath();c.arc(X,Y,R,PI*.68,PI*2.32);c.quadraticCurveTo(156,150,158,166);c.lineTo(98,166);c.quadraticCurveTo(100,150,X-R*cos(PI*.32),Y+R*sin(PI*.32));c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=7;c.beginPath();c.arc(X,Y,R-14,PI*1.12,PI*1.42);c.stroke();c.strokeStyle='#111'
|
||||||
|
// face
|
||||||
|
const ey=116;c.fillStyle='#111';c.lineWidth=5
|
||||||
|
if(ph==0){for(const d of[-1,1])c.beginPath(),c.arc(X+d*20,ey,5.5,0,T),c.fill();c.beginPath();c.moveTo(X-8,140);c.quadraticCurveTo(X,136,X+8,140);c.stroke();c.lineWidth=4;c.beginPath();c.moveTo(X+10,ey-16);c.lineTo(X+28,ey-20);c.stroke()}
|
||||||
|
else if(ph==1){for(const d of[-1,1]){c.fillStyle='#111';c.beginPath();c.arc(X+d*20,ey,9,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(X+d*20+3,ey-3,3.5,0,T);c.fill()}c.fillStyle='#ff8787';c.beginPath();c.moveTo(X-16,134);c.quadraticCurveTo(X,162,X+16,134);c.closePath();c.fill();c.stroke()}
|
||||||
|
else if(ph==2){for(const d of[-1,1])c.beginPath(),c.arc(X+d*20,ey,7,0,T),c.fill();c.beginPath();c.moveTo(X-12,144);for(let k=1;k<=4;k++)c.lineTo(X-12+k*6,144+(k%2?-4:0));c.stroke()}
|
||||||
|
else{for(const d of[-1,1])c.beginPath(),c.arc(X+d*20,ey+2,4,0,T),c.fill();c.lineWidth=4;c.beginPath();c.moveTo(X-10,144);c.lineTo(X+10,144);c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
// the idea, then the lack of it
|
||||||
|
if(ph==1){const s=pop((i-3)/2);c.save();c.translate(X,46);c.scale(s,s);txt(c,'!',0,-36,6,'#ffd43b',9);c.restore()}
|
||||||
|
if(ph==3){const s=pop((i-17)/2);c.save();c.translate(X+56,48);c.rotate(.15);c.scale(s,s);txt(c,'?',0,-21,6.4,'#fff',9);c.restore()}
|
||||||
|
// smoke puff
|
||||||
|
if(i>=15&&i<22){const q=(i-15)/7;c.fillStyle='#ced4da';c.lineWidth=5;for(let k=0;k<3;k++){const r=(8+k*3)*(1-q*.4),x=X-24+sin(q*6+k*2)*8,y=60-q*40-k*14;if(q*3>k){c.beginPath();c.arc(x,y,r,0,T);c.fill();c.stroke()}}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// blob back from vacation opens the laptop, 999+ pops up and an avalanche of envelopes piles up over it until a white flag pokes out, then poof, back to the start
|
||||||
|
const{sin,cos,PI,max,min,abs,sqrt}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=100,rim=5
|
||||||
|
const Y='#ffd43b',BL='#ff8787',LG='#ced4da',LD='#868e96',EC=['#fff','#d0ebff','#fff','#fff3bf','#fff','#ffdeeb'],RD='#fa5252'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const R=n=>abs(sin(n*127.1+311.7)*43758.5)%1
|
||||||
|
const P=[];for(let r=0;r<11;r++)for(let k=0;k<8;k++)P.push([6+k*34+(r%2?17:0)+(R(r*10+k)-.5)*8,238-r*19,(R(r*10+k+300)-.5)*.9,EC[(r*3+k)%6]])
|
||||||
|
const env=(c,x,y,a,col)=>{c.save();c.translate(x,y);c.rotate(a);c.fillStyle=col;c.lineWidth=4;c.beginPath();c.roundRect(-19,-13,38,26,3);c.fill();c.stroke();c.lineWidth=3;c.beginPath();c.moveTo(-16,-10);c.lineTo(0,3);c.lineTo(16,-10);c.stroke();c.restore()}
|
||||||
|
const SG=[63,6,91,79,102,109,125,7,127,111],SP=[[0,0,1,0],[1,0,1,.5],[1,.5,1,1],[0,1,1,1],[0,.5,0,1],[0,0,0,.5],[0,.5,1,.5]]
|
||||||
|
const dig=(c,x,y,n,w,h)=>SP.forEach(([a,b,e,f],k)=>{if(SG[n]>>k&1)c.moveTo(x+a*w,y+b*h),c.lineTo(x+e*w,y+f*h)})
|
||||||
|
const cloud=(c,s)=>{const B=[[128,140,62],[70,168,42],[186,168,42],[88,104,38],[168,104,38],[128,82,36],[128,196,44],[34,196,34],[222,196,34],[40,122,16],[214,118,14],[200,54,10]];c.lineWidth=14*s;for(const[x,y,r]of B)c.beginPath(),c.arc(128+(x-128)*s,140+(y-140)*s,r*s,0,T),c.stroke();c.fillStyle='#f1f3f5';for(const[x,y,r]of B)c.beginPath(),c.arc(128+(x-128)*s,140+(y-140)*s,r*s,0,T),c.fill()}
|
||||||
|
export default(c,t)=>{
|
||||||
|
const reset=t>=.9,open=reset?0:ez(t,.06,.14),lt=214-84*open,shock=t>=.16&&!reset,H=reset?0:182*ez(t,.18,.64)
|
||||||
|
// blob behind the laptop
|
||||||
|
c.fillStyle=Y;c.beginPath();c.moveTo(62,222);c.bezierCurveTo(56,110,84,58,128,58);c.bezierCurveTo(172,58,200,110,194,222);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#212529';c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.roundRect(128+d*24-15,70,30,18,7),c.fill(),c.stroke()
|
||||||
|
c.beginPath();c.moveTo(119,78);c.lineTo(137,78);c.stroke()
|
||||||
|
c.fillStyle='#ff6b6b';c.lineWidth=4;for(let k=0;k<5;k++){const a=k*T/5;c.beginPath();c.ellipse(180+cos(a)*8,88+sin(a)*8,6,4,a,0,T);c.fill();c.stroke()}c.fillStyle=Y;c.beginPath();c.arc(180,88,4,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*40,128,10,5,0,0,T),c.fill()
|
||||||
|
if(shock){for(const d of[-1,1]){c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(128+d*22,110,12,0,T);c.fill();c.stroke();c.fillStyle='#111';c.beginPath();c.arc(128+d*22,110,3.5,0,T);c.fill()}
|
||||||
|
c.fillStyle='#c92a2a';c.lineWidth=4;c.beginPath();c.ellipse(128,136,8,10,0,0,T);c.fill();c.stroke()}
|
||||||
|
else{c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.arc(128+d*22,114,8,PI*1.1,PI*1.9),c.stroke()
|
||||||
|
c.beginPath();c.arc(128,124,12,.15*PI,.85*PI);c.stroke()}
|
||||||
|
// the heap rising up over it
|
||||||
|
const top=x=>236-H*sqrt(max(0,1-((x-128)/128)**4))
|
||||||
|
for(const[x,y,a,col]of P)if(y>top(x)+4)env(c,x,y,a,col)
|
||||||
|
// white flag of surrender
|
||||||
|
if(t>=.64&&!reset){const u=ez(t,.64,.7),fx=92,fy=top(92)+30-34*u,w=sin(t*T*6)
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(fx,fy);c.lineTo(fx,fy-38);c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4.5;c.beginPath();c.moveTo(fx,fy-38);c.quadraticCurveTo(fx+13,fy-44+4*w,fx+28,fy-36);c.lineTo(fx+28,fy-16);c.quadraticCurveTo(fx+13,fy-24-4*w,fx,fy-18);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=Y;c.lineWidth=6;c.beginPath();c.ellipse(fx,fy,12,13,0,0,T);c.fill();c.stroke()
|
||||||
|
if(u<1)env(c,fx-12,top(92)+8,.3,'#fff')}
|
||||||
|
// laptop
|
||||||
|
c.lineWidth=6;c.fillStyle=LD;c.beginPath();c.moveTo(36,214);c.lineTo(220,214);c.lineTo(232,234);c.lineTo(24,234);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=LG;c.beginPath();c.moveTo(42,214);c.lineTo(214,214);c.lineTo(214-6*open,lt);c.lineTo(42+6*open,lt);c.closePath();c.fill();c.stroke()
|
||||||
|
if(open>.5){c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(128,lt+(214-lt)*.45,9,0,T);c.fill();c.stroke()}
|
||||||
|
// envelopes geysering out of the screen
|
||||||
|
if(t>=.16&&t<.62)for(let k=0;k<7;k++){const p=(t*9+k/7)%1,d=k%2?1:-1,x=128+d*(10+p*(40+R(k)*60)),y=150-170*p+(150+H*.4)*p*p;env(c,x,y,(p*4+k)*d,EC[k%6])}
|
||||||
|
// 999+ badge
|
||||||
|
const bs=reset?0:ez(t,.14,.18),bp=1+.25*sin(ez(t,.14,.24)*PI)
|
||||||
|
if(bs>.05){c.save();c.translate(190,46);c.scale(bs*bp,bs*bp);c.rotate(.12)
|
||||||
|
c.fillStyle=RD;c.lineWidth=6;c.beginPath();c.roundRect(-42,-21,84,42,21);c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();for(let k=0;k<3;k++)dig(c,-30+k*17,-11,9,9,22);c.moveTo(22,0);c.lineTo(36,0);c.moveTo(29,-7);c.lineTo(29,7);c.stroke()
|
||||||
|
c.restore();c.strokeStyle='#111'}
|
||||||
|
// poof back to the start
|
||||||
|
if(t>=.82){const s=t<.9?ez(t,.82,.9):1-ez(t,.9,1);if(s>.03)cloud(c,.3+s*.9)}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// two fists hammering a keyboard in turn, the home row letters A S D F G H J K L bursting out of their keys and flying everywhere
|
||||||
|
const{sin,cos,PI,abs,min,max}=Math,T=2*PI
|
||||||
|
export const frames=12,delay=Array(12).fill(65),rim=4
|
||||||
|
const G={A:'M0 6L2 0L4 6M.7 4L3.3 4',S:'M3.8 .9Q3.1 0 2 0Q.2 0 .2 1.5Q.2 2.8 2 3Q3.9 3.2 3.9 4.5Q3.9 6 2 6Q.7 6 0 5.1',D:'M0 0L0 6L1.7 6Q4 6 4 3Q4 0 1.7 0L0 0',F:'M4 0L0 0L0 6M0 3L3.2 3',G:'M4 .9Q3.3 0 2.1 0Q0 0 0 3Q0 6 2.1 6Q4 6 4 3.6L2.4 3.6',H:'M0 0L0 6M4 0L4 6M0 3L4 3',J:'M4 0L4 4.2Q4 6 2 6Q0 6 0 4.4',K:'M0 0L0 6M4 0L0 3.8M1.4 2.7L4 6',L:'M0 0L0 6L4 6'}
|
||||||
|
const txt=(c,s,x,y,k,col,w)=>{
|
||||||
|
const a=5.4*k,W=s.length*a-1.4*k;c.beginPath()
|
||||||
|
;[...s].forEach((ch,j)=>{const ox=x-W/2+j*a;for(const[,o,q]of(G[ch]||'').matchAll(/([MLQ])([^MLQ]*)/g)){const n=q.trim().split(/[ ,]+/).map((v,m)=>m%2?y+v*k:ox+v*k);o=='M'?c.moveTo(...n):o=='L'?c.lineTo(...n):c.quadraticCurveTo(...n)}})
|
||||||
|
for(const[l,s]of[[w+6,'#111'],[w,col]])c.lineWidth=l,c.strokeStyle=s,c.stroke();c.strokeStyle='#111'
|
||||||
|
}
|
||||||
|
const SK='#ffd8b5',SL='#748ffc',KB='#adb5bd',COL=['#ffd43b','#69db7c','#4dabf7','#f783ac','#ffa94d','#b197fc','#ffd43b','#69db7c','#4dabf7'],HR='ASDFGHJKL'
|
||||||
|
const key=(r,k)=>{const s=.86+r*.08;return[128+(k-4.5+r*.2)*19*s,170+r*22,16.5*s]}
|
||||||
|
const fist=(c,x,y)=>{
|
||||||
|
c.fillStyle=SL;c.lineWidth=7;c.beginPath();c.roundRect(x-22,-20,44,y+14,6);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SK;c.beginPath();c.roundRect(x-32,y-18,64,42,16);c.fill();c.stroke()
|
||||||
|
c.lineWidth=5;for(let k=0;k<4;k++)c.beginPath(),c.roundRect(x-32+k*16,y+2,16,30,8),c.fill(),c.stroke()
|
||||||
|
c.beginPath();c.roundRect(x-34,y-6,42,17,8.5);c.fill();c.stroke()
|
||||||
|
}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const hit=[0,1].map(f=>abs(sin(PI*(t*3+f*.5)))),fy=hit.map(h=>134-h*96),shk=min(...hit)<.2?2:0
|
||||||
|
// keyboard
|
||||||
|
c.save();c.translate(0,shk)
|
||||||
|
c.fillStyle=KB;c.lineWidth=7;c.beginPath();c.moveTo(34,152);c.lineTo(222,152);c.lineTo(244,240);c.lineTo(12,240);c.closePath();c.fill();c.stroke()
|
||||||
|
for(let r=0;r<3;r++)for(let k=0;k<10;k++){const[x,y,w]=key(r,k),p=fy.some((f,n)=>hit[n]<.25&&abs(x-(n?172:84))<34&&r<2)?3:0
|
||||||
|
c.fillStyle='#495057';c.lineWidth=3;c.beginPath();c.roundRect(x-w/2,y-7+4,w,18,4);c.fill();c.stroke()
|
||||||
|
c.fillStyle=r==1?'#fff':'#f1f3f5';c.beginPath();c.roundRect(x-w/2,y-7+p,w,15,4);c.fill();c.stroke()}
|
||||||
|
c.fillStyle='#495057';c.lineWidth=3;c.beginPath();c.roundRect(84,228-14,88,14,4);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// flying letters, each from its own home row key
|
||||||
|
for(let j=0;j<9;j++){const a=(t+j*5/9)%1;if(a>.6)continue;const[x0,y0]=key(1,j),dir=(j-4)/4,x=x0+dir*a*170+(j%2?14:-14)*a,y=y0-460*a+640*a*a,s=min(1,a*10)
|
||||||
|
c.save();c.translate(x,y);c.rotate(dir*a*4+(j%2?.3:-.3)*a*3);c.scale(s,s);txt(c,HR[j],0,-14,4.4,COL[j],6);c.restore()}
|
||||||
|
// impact bursts
|
||||||
|
hit.forEach((h,n)=>{if(h>.3)return;const x=n?172:84;c.lineWidth=5;for(const a of[-2.8,-2.3,-.85,-.35]){c.beginPath();c.moveTo(x+cos(a)*46,166+sin(a)*26);c.lineTo(x+cos(a)*66,166+sin(a)*40);c.stroke()}})
|
||||||
|
fy.forEach((y,n)=>fist(c,n?172:84,y))
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// typing LMAO with a dead straight face: the letters pop into the chat bubble and laugh their heads off while the face never moves
|
||||||
|
import{Path2D}from'@napi-rs/canvas'
|
||||||
|
const{sin,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
const U=[0,.07,.14,.21,.28,.35,...Array.from({length:10},(_,k)=>.4+k*.05),.9,.95]
|
||||||
|
export const frames=U.length,delay=[400,140,140,140,140,160,...Array(10).fill(70),90,250],rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u*u*(3-2*u)),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||||
|
const K='#1b1b1f',B='#4dabf7',G='#c3fae8'
|
||||||
|
const F={L:'M0 0V10H6',M:'M0 10V0L3.5 6L7 0V10',A:'M0 10L3 0L6 10M1 6.5H5',O:'M3 0A3 5 0 1 1 3 10A3 5 0 1 1 3 0Z'}
|
||||||
|
const L=(c,ch,x,y,s,a)=>{c.save();c.translate(x,y);c.rotate(a);c.scale(s*4.4,s*4.4);c.translate(ch=='M'?-3.5:-3,-5);for(const[w,st]of[[5.6,K],[2.4,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.stroke(new Path2D(F[ch]));c.restore()}
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=U[i],lol=t>=.4&&t<.9,ph=T*(t-.4)*4,out=io((t-.88)/.06)
|
||||||
|
// the bubble
|
||||||
|
const bw=lol?3*sin(ph*1.5):0
|
||||||
|
c.save();c.translate(128,64);c.rotate(.02*bw);c.translate(-128,-64)
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle=B;c.beginPath();c.roundRect(20,18,216,92,30);c.fill()
|
||||||
|
c.beginPath();c.moveTo(168,100);c.lineTo(190,136);c.lineTo(196,100);c.fill();c.beginPath();c.moveTo(168,108);c.lineTo(190,136);c.lineTo(198,108)
|
||||||
|
c.stroke();c.beginPath();c.roundRect(20,18,216,92,30);c.stroke();c.fillStyle=B;c.fillRect(170,100,26,14)
|
||||||
|
c.restore()
|
||||||
|
if(t<.05){c.fillStyle='#fff';for(const x of[100,128,156])c.beginPath(),c.arc(x,64,9,0,T),c.fill()}
|
||||||
|
;[...'LMAO'].forEach((ch,k)=>{const s=bk((t-.05-k*.07)/.05)*(1-out);if(s<.02)return
|
||||||
|
const b=lol?abs(sin(ph+k*.9)):0,x=50+k*52+(ch=='M'?2:0)
|
||||||
|
L(c,ch,x,66-14*b,s*(1+.12*b),lol?.22*sin(ph*.5*3+k*1.7):0)
|
||||||
|
})
|
||||||
|
// the face never moves
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle=G
|
||||||
|
c.beginPath();c.moveTo(100,153);c.quadraticCurveTo(94,134,108,130);c.stroke()
|
||||||
|
c.beginPath();c.ellipse(102,202,70,50,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=K;for(const x of[78,122])c.beginPath(),c.roundRect(x-10,186,20,7,3),c.fill()
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(89,214);c.lineTo(111,214);c.stroke()
|
||||||
|
// phone and tapping thumbs
|
||||||
|
c.lineWidth=6;c.fillStyle='#495057';c.beginPath();c.roundRect(154,180,52,68,10);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#868e96';c.beginPath();c.arc(180,194,5,0,T);c.fill()
|
||||||
|
const tp=t<.38?(i%2):0
|
||||||
|
c.fillStyle=G;for(const[x,d]of[[156,0],[204,1]]){c.beginPath();c.ellipse(x,226-(d==tp?6:0),13,15,0,0,T);c.fill();c.stroke()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
// main character energy: shades on, scarf in the wind, strutting in his own spotlight with sparkles while grey extras drift past in the background
|
||||||
|
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||||
|
export const frames=12,delay=Array(12).fill(90),rim=4
|
||||||
|
const K='#1b1b1f',B='#ff8787'
|
||||||
|
const spark=(c,x,y,r)=>{c.beginPath();for(let k=0;k<8;k++){const a=k*PI/4,q=k%2?r*.32:r;c.lineTo(x+q*cos(a),y+q*sin(a))}c.closePath();c.fill();c.stroke()}
|
||||||
|
export default(c,t)=>{
|
||||||
|
const ph=T*t*2,bob=abs(sin(ph)),s=sin(ph)
|
||||||
|
// spotlight, then the background extras sliding past, identical and all the same grey
|
||||||
|
c.fillStyle='#fff3bf';c.beginPath();c.moveTo(106,0);c.lineTo(150,0);c.lineTo(216,236);c.quadraticCurveTo(128,256,40,236);c.closePath();c.fill()
|
||||||
|
c.strokeStyle='#868e96';c.lineWidth=4
|
||||||
|
for(let k=0;k<5;k++){const x=((k*64-t*64)%320+320)%320-32,h=26,y=176-h
|
||||||
|
c.fillStyle='#dee2e6';c.beginPath();c.ellipse(x,y,19,h,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#868e96';for(const d of[-6,6])c.beginPath(),c.arc(x+d,y-h*.35,2.5,0,T),c.fill()
|
||||||
|
c.beginPath();c.moveTo(x-5,y-h*.35+9);c.lineTo(x+5,y-h*.35+9);c.stroke()}
|
||||||
|
c.save();c.translate(128,236);c.rotate(.05*s);c.translate(-128,-236-7*bob);c.strokeStyle=K;c.lineWidth=6
|
||||||
|
// legs and arms swing opposite
|
||||||
|
for(const[d,lf]of[[-1,s],[1,-s]]){const hx=128+d*14,fx=hx+24*lf,up=lf>.2?10*lf:0
|
||||||
|
for(const[w,st]of[[20,K],[9,'#4c6ef5']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(hx,184),c.lineTo(fx,226-up),c.stroke()
|
||||||
|
c.fillStyle=K;c.beginPath();c.ellipse(fx+6,232-up,15,8,0,0,T);c.fill()}
|
||||||
|
for(const[d,sw]of[[-1,-s],[1,s]]){const sx=128+d*38,hx=sx+d*8+22*sw,hy=194
|
||||||
|
for(const[w,st]of[[20,K],[9,B]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(sx,160),c.lineTo(hx,hy),c.stroke()
|
||||||
|
c.fillStyle=B;c.strokeStyle=K;c.lineWidth=5;c.beginPath();c.arc(hx,hy,10,0,T);c.fill();c.stroke()}
|
||||||
|
// scarf tails stream behind in the wind
|
||||||
|
c.fillStyle='#ffd43b';c.strokeStyle=K;c.lineWidth=5
|
||||||
|
for(const[o,w]of[[0,17],[1,13]]){const y=k=>158+o*13-k*(o?.6:1.8)+7*sin(ph*2-k*.55+o*1.5)*k/10;c.beginPath();for(let k=0;k<=10;k++)c.lineTo(100-8.5*k,y(k));for(let k=10;k>=0;k--)c.lineTo(100-8.5*k,y(k)+w*(1-k/30));c.closePath();c.fill();c.stroke()}
|
||||||
|
c.fillStyle=B;c.lineWidth=6;c.beginPath();c.ellipse(128,140,46,54,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.globalAlpha=.5;c.beginPath();c.ellipse(104,106,8,14,.5,0,T);c.fill();c.globalAlpha=1
|
||||||
|
c.fillStyle='#ffd43b';c.lineWidth=5;c.beginPath();c.moveTo(84,158);c.quadraticCurveTo(128,176,172,158);c.lineTo(172,172);c.quadraticCurveTo(128,190,84,172);c.closePath();c.fill();c.stroke()
|
||||||
|
// shades and a smirk
|
||||||
|
c.fillStyle=K;c.lineWidth=5;c.beginPath();c.moveTo(94,112);c.lineTo(162,112);c.stroke()
|
||||||
|
for(const x of[112,146]){c.beginPath();c.roundRect(x-16,108,32,19,[3,3,13,13]);c.fill()}
|
||||||
|
c.fillStyle='#fff';for(const x of[103,137])c.beginPath(),c.moveTo(x,112),c.lineTo(x+8,112),c.lineTo(x+2,121),c.closePath(),c.fill()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(116,142);c.quadraticCurveTo(136,150,148,136);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
c.strokeStyle=K;c.lineWidth=3;c.fillStyle='#ffe066'
|
||||||
|
for(const[x,y,o]of[[56,70,0],[200,58,.33],[212,150,.66]]){const r=12*abs(sin(PI*((t*2+o)%1)));if(r>2)spark(c,x,y,r)}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// a hand lets go of a mic, it hits the stage with a huge BOOM, then the hand casually reaches down and picks it up to drop it all over again
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=30,delay=80,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)},pop=u=>(u=cl(u),u<.6?1.2*u/.6:1.2-.2*(u-.6)/.4)
|
||||||
|
const G={B:'0c006082846606 66888a6c0c',O:'2060828a6c2c0a0220',M:'0c0056a0ac'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const HX=92,HY=92,FY=198,SK='#f2c79a'
|
||||||
|
// mic with its grip point at the origin, head up
|
||||||
|
const mic=(c,x,y,r)=>{c.save();c.translate(x,y);c.rotate(r);c.strokeStyle='#111'
|
||||||
|
c.fillStyle='#343a40';c.lineWidth=5;c.beginPath();c.moveTo(-8,-14);c.lineTo(8,-14);c.lineTo(5,42);c.quadraticCurveTo(0,46,-5,42);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#868e96';c.beginPath();c.roundRect(-11,-24,22,12,3);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ced4da';c.beginPath();c.arc(0,-40,17,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.clip();c.strokeStyle='#868e96';c.lineWidth=2;for(let k=-3;k<=3;k++)c.beginPath(),c.moveTo(k*6-12,-58),c.lineTo(k*6+12,-22),c.moveTo(k*6+12,-58),c.lineTo(k*6-12,-22),c.stroke();c.restore()
|
||||||
|
c.lineWidth=5;c.beginPath();c.arc(0,-40,17,0,T);c.stroke();c.restore()}
|
||||||
|
// arm reaches in from the left edge, fist (or open hand) centred on (x,y)
|
||||||
|
const hand=(c,x,y,open)=>{const ay=y-8-(y-HY)*.55
|
||||||
|
for(const[w,s]of[[34,'#111'],[24,'#4c6ef5']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(-40,ay),c.lineTo(x-24,y),c.stroke()
|
||||||
|
const a=Math.atan2(y-ay,x-24+40);c.save();c.translate(x-24,y);c.rotate(a);c.fillStyle='#364fc7';c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.roundRect(-8,-17,12,34,4);c.fill();c.stroke();c.restore()
|
||||||
|
c.fillStyle=SK;c.strokeStyle='#111'
|
||||||
|
if(open){for(const[a,l]of[[-.5,22],[-.1,26],[.3,25],[.7,21]]){c.save();c.translate(x-4,y);c.rotate(a);for(const[w,s]of[[14,'#111'],[5,SK]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(0,0),c.lineTo(l,0),c.stroke();c.restore()}
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.ellipse(x-6,y,15,16,0,0,T);c.fill();c.stroke()}
|
||||||
|
else{c.lineWidth=5;c.beginPath();c.roundRect(x-18,y-16,34,32,12);c.fill();c.stroke();c.lineWidth=3;for(const yy of[-6,2,10])c.beginPath(),c.moveTo(x+4,y+yy),c.lineTo(x+16,y+yy),c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();c.ellipse(x-2,y-14,13,6,0,0,T);c.fill();c.stroke()}}
|
||||||
|
const burst=(c,x,y,s,i)=>{c.save();c.translate(x,y);c.scale(s,s);c.rotate(((i>>1)%2)*.04);c.fillStyle='#ffd43b';c.lineWidth=6/s;c.strokeStyle='#111';c.beginPath()
|
||||||
|
for(let k=0;k<28;k++){const a=k*PI/14,r=k%2?44:66+(k%4?0:8);c.lineTo(r*cos(a)*1.12,r*sin(a)*.9)}c.closePath();c.fill();c.stroke()
|
||||||
|
txt(c,'BOOM',0,0,26,'#ff6b6b');c.restore()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
// grip point of the mic and where the hand is
|
||||||
|
let mx=HX,my=HY,mr=0,hx=HX,hy=HY,open=0
|
||||||
|
if(t<.16)mr=-.08*sin(t/.16*PI)
|
||||||
|
else if(t<.4){const u=cl((t-.18)/.22);open=1;mx=HX+10*u;my=HY+(FY-HY)*u*u;mr=PI/2*u;if(t<.18)my=HY}
|
||||||
|
else if(t<.76){const v=cl((t-.4)/.1);open=1;mx=HX+10;my=FY-16*sin(PI*v);mr=PI/2+.25*sin(PI*v)}
|
||||||
|
else{const d=ez(t,.76,.86),g=ez(t,.88,.99);open=t<.86;mx=HX+10-10*g;my=FY+(HY-FY)*g;mr=PI/2*(1-g);hx=HX+10*d-10*g;hy=HY+(FY-HY)*d+(HY-FY)*g}
|
||||||
|
// stage
|
||||||
|
c.fillStyle='#c08a5b';c.lineWidth=6;c.beginPath();c.roundRect(12,214,232,26,8);c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#8c5a33';c.lineWidth=3;for(const x of[70,140,200])c.beginPath(),c.moveTo(x,218),c.lineTo(x,236),c.stroke()
|
||||||
|
const hit=t>=.4&&t<.76,hk=cl((t-.4)/.36)
|
||||||
|
if(hit){const s=pop(hk*4)*(1-ez(t,.7,.76));burst(c,176,126,s*.88,i)
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;const e=6+10*min(1,hk*3);for(const[a,b]of[[-2.6,1],[-2.2,1],[-.9,1],[-.5,1]]){const cx=HX+40,cy=212;c.beginPath();c.moveTo(cx+cos(a)*(40+e),cy+sin(a)*(22+e));c.lineTo(cx+cos(a)*(56+e),cy+sin(a)*(30+e));c.stroke()}}
|
||||||
|
mic(c,mx,my,mr)
|
||||||
|
hand(c,hx,hy,open)
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// microwave counting down, a hand sneaks in and pops the door open at 0:01 right before it can beep, then the door swings shut and it starts over
|
||||||
|
const{sin,cos,PI,max,min,floor}=Math,T=2*PI
|
||||||
|
export const frames=32,delay=90,rim=5
|
||||||
|
const BODY='#e9ecef',DK='#adb5bd',WIN='#343a40',LIT='#ffe066',CAV='#fff3bf',SEG='#69db7c',MUG='#4dabf7',SK='#ffd43b',SL='#9775fa',BTN='#ff8787'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const SG=[63,6,91,79,102,109,125,7,127,111],SP=[[0,0,1,0],[1,0,1,.5],[1,.5,1,1],[0,1,1,1],[0,.5,0,1],[0,0,0,.5],[0,.5,1,.5]]
|
||||||
|
const dig=(c,x,y,n)=>{c.beginPath();SP.forEach(([a,b,e,f],k)=>{if(SG[n]>>k&1){const g=a==e?.14:.2,h=a==e?.1:0;c.moveTo(x+(a+(e-a)*g)*9+h,y+(b+(f-b)*g)*18);c.lineTo(x+(e-(e-a)*g)*9+h,y+(f-(f-b)*g)*18)}});c.stroke()}
|
||||||
|
const mug=(c,x,y,a)=>{const hs=sin(a)
|
||||||
|
if(cos(a)<0)c.lineWidth=5,c.beginPath(),c.arc(x+hs*16,y-12,8,0,T),c.stroke()
|
||||||
|
c.lineWidth=5;c.fillStyle=MUG;c.beginPath();c.roundRect(x-15,y-28,30,30,[2,2,7,7]);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.ellipse(x,y-28,15,4,0,0,T);c.fill();c.stroke()
|
||||||
|
if(cos(a)>=0)c.beginPath(),c.arc(x+hs*16,y-12,8,0,T),c.stroke()
|
||||||
|
}
|
||||||
|
const hand=(c,x,y,a)=>{c.save();c.translate(x,y);c.rotate(a);c.lineWidth=6
|
||||||
|
c.fillStyle=SL;c.beginPath();c.roundRect(58,-18,140,44,8);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.roundRect(52,-20,14,48,6);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SK;c.beginPath();c.roundRect(-4,-7,46,15,7.5);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(22,-12,34,36,12);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(30,10);c.lineTo(44,10);c.moveTo(30,18);c.lineTo(44,18);c.stroke()
|
||||||
|
c.restore()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const n=t>=.9||t<.12?4:t<.24?3:t<.36?2:1,run=t<.43||t>=.9,op=ez(t,.43,.48)*(1+.12*sin(ez(t,.48,.62)*PI))-ez(t,.8,.9),ang=op*1.25
|
||||||
|
const press=t>=.39&&t<.48,tbl=(t<.43?t:t>=.9?t-.47:.43)*T*2.2
|
||||||
|
// sneaky hand: creeps in from the right, jabs at 0:01, slides away
|
||||||
|
const cr=ez(t,.14,.34),jab=ez(t,.36,.39),out=ez(t,.5,.64),tr=t>.2&&t<.36?1.5*sin(i*3):0
|
||||||
|
const hx=184+110*(1-cr)+14*(cr-jab)+110*out,hy=172+80*(1-cr)+12*(cr-jab)+80*out
|
||||||
|
c.save();c.translate(4,12);c.scale(.88,.88)
|
||||||
|
c.fillStyle=DK;for(const x of[40,216])c.beginPath(),c.roundRect(x-14,198,28,14,4),c.fill(),c.stroke()
|
||||||
|
c.fillStyle=BODY;c.beginPath();c.roundRect(10,58,236,148,16);c.fill();c.stroke()
|
||||||
|
// cavity
|
||||||
|
c.fillStyle=CAV;c.beginPath();c.roundRect(24,70,136,124,8);c.fill();c.stroke()
|
||||||
|
c.save();c.beginPath();c.roundRect(24,70,136,124,8);c.clip()
|
||||||
|
c.fillStyle='#ffd43b';c.beginPath();c.moveTo(24,70);c.lineTo(46,90);c.lineTo(46,172);c.lineTo(24,194);c.fill()
|
||||||
|
c.fillStyle='#ffec99';c.beginPath();c.moveTo(160,70);c.lineTo(138,90);c.lineTo(138,172);c.lineTo(160,194);c.fill()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(46,90);c.lineTo(138,90);c.lineTo(138,172);c.lineTo(46,172);c.closePath();c.moveTo(24,70);c.lineTo(46,90);c.moveTo(160,70);c.lineTo(138,90);c.moveTo(24,194);c.lineTo(46,172);c.moveTo(160,194);c.lineTo(138,172);c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.ellipse(92,172,48,10,0,0,T);c.fill();c.stroke()
|
||||||
|
mug(c,92+sin(tbl)*22,170+cos(tbl)*3,tbl)
|
||||||
|
if(!run){c.strokeStyle='#868e96';c.lineWidth=4;for(let k=0;k<3;k++){const ph=(t*3+k/3)%1,x0=86+k*9;c.globalAlpha=1-ph;c.beginPath();for(let y=0;y<16;y+=2)c.lineTo(x0+3*sin(y/3+ph*8),132-ph*26-y);c.stroke()}c.globalAlpha=1;c.strokeStyle='#111'}
|
||||||
|
c.restore()
|
||||||
|
// door, hinged on the left, swings toward us
|
||||||
|
const w=136*cos(ang),gr=14*sin(ang)
|
||||||
|
c.fillStyle=ang>PI/2?DK:BODY;c.lineWidth=6
|
||||||
|
c.beginPath();c.moveTo(22,68);c.lineTo(22+w,68-gr);c.lineTo(22+w,196+gr);c.lineTo(22,196);c.closePath();c.fill();c.stroke()
|
||||||
|
if(cos(ang)>.25){const f=v=>22+v*w/136,g=(v,y)=>y+(y<132?-1:1)*gr*v/136*(y<132?(132-y)/64:(y-132)/64)
|
||||||
|
c.fillStyle=LIT;c.beginPath();c.moveTo(f(12),g(12,82));c.lineTo(f(124),g(124,82));c.lineTo(f(124),g(124,182));c.lineTo(f(12),g(12,182));c.closePath();c.fill();c.stroke()
|
||||||
|
if(run&&op<.05){c.save();c.beginPath();c.roundRect(34,82,112,100,4);c.clip();c.fillStyle='#fff';c.beginPath();c.ellipse(90,170,40,8,0,0,T);c.fill();c.lineWidth=4;c.stroke();c.lineWidth=5;mug(c,90+sin(tbl)*20,168+cos(tbl)*3,tbl)
|
||||||
|
c.fillStyle='rgba(52,58,64,.28)';for(let y=86;y<182;y+=8)for(let x=38+(y%16?4:0);x<146;x+=8)c.fillRect(x,y,3,3);c.restore()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.moveTo(48,98);c.lineTo(60,92);c.moveTo(48,112);c.lineTo(74,98);c.stroke();c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.roundRect(34,82,112,100,4);c.stroke()}
|
||||||
|
}
|
||||||
|
// panel
|
||||||
|
c.lineWidth=6;c.fillStyle='#212529';c.beginPath();c.roundRect(170,72,62,36,6);c.fill();c.stroke()
|
||||||
|
const blink=t>.52&&t<.8&&i%2
|
||||||
|
c.strokeStyle=SEG;c.lineWidth=3.5
|
||||||
|
if(!blink){dig(c,178,81,0);dig(c,199,81,0);dig(c,215,81,n);c.fillStyle=SEG;for(const y of[86,94])c.beginPath(),c.arc(191,y,2,0,T),c.fill()}
|
||||||
|
c.strokeStyle='#111';c.lineWidth=4;c.fillStyle='#f8f9fa'
|
||||||
|
for(let r=0;r<3;r++)for(let k=0;k<3;k++)c.beginPath(),c.roundRect(176+k*20,118+r*15,12,9,3),c.fill(),c.stroke()
|
||||||
|
c.lineWidth=6;c.fillStyle=press?'#e03131':BTN;c.beginPath();c.roundRect(176,167+(press?3:0),52,22-(press?3:0),11);c.fill();c.stroke()
|
||||||
|
if(t>=.39&&t<.52){const p=ez(t,.39,.48);for(let k=0;k<5;k++){const a=-PI*.95+k*PI*.5/2;for(const[lw,s]of[[9,'#111'],[4,'#fff']])c.lineWidth=lw,c.strokeStyle=s,c.beginPath(),c.moveTo(202+cos(a)*(34+10*p),178+sin(a)*(20+8*p)),c.lineTo(202+cos(a)*(46+14*p),178+sin(a)*(28+10*p)),c.stroke()}c.strokeStyle='#111'}
|
||||||
|
c.restore()
|
||||||
|
if(hx<300)c.save(),c.translate(hx+tr,hy),c.scale(1.5,1.5),hand(c,0,0,.62),c.restore()
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// mind blown: eyes go wide, the top of the head pops off in a burst of confetti, flips through the air and lands back on with a bonk, leaving it dizzy
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
const U=[0,.1,.17,.2,.23,.28,.36,.46,.55,.6,.63,.68,.76,.84,.92,.97]
|
||||||
|
export const frames=U.length,delay=[350,100,140,50,60,70,80,80,70,50,70,110,110,110,130,220],rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u*u*(3-2*u)),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||||
|
const K='#1b1b1f',H='#b197fc',HL='#d0bfff',P='#f783ac',CF=['#ff6b6b','#ffd43b','#69db7c','#4dabf7','#f783ac','#ff922b']
|
||||||
|
const CX=128,CY=150,R=74,Z=[[50,112],[70,104],[90,118],[110,104],[128,118],[146,104],[166,118],[186,104],[206,112]]
|
||||||
|
const zig=c=>{c.moveTo(...Z[0]);for(const p of Z)c.lineTo(...p)}
|
||||||
|
const star=(c,x,y,r,n,q,a=0)=>{c.beginPath();for(let k=0;k<2*n;k++){const rr=k%2?r*q:r,b=a+k*PI/n-PI/2;c.lineTo(x+rr*cos(b),y+rr*sin(b))}c.closePath()}
|
||||||
|
const hand=(c,x,y,a,sp)=>{c.save();c.translate(x,y);c.rotate(a);c.fillStyle=H;c.lineWidth=5
|
||||||
|
for(const k of[-1,0,1])c.beginPath(),c.roundRect(-5+k*(9+5*sp),-20-5*sp*(1-abs(k)),10,20,5),c.fill(),c.stroke()
|
||||||
|
c.beginPath();c.arc(0,4,14,0,T);c.fill();c.stroke();c.restore()}
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=U[i],wide=io((t-.06)/.12)*(1-io((t-.88)/.09)),boom=t>=.2&&t<.62,dz=t>=.63&&t<.92,u=cl((t-.2)/.42)
|
||||||
|
const ly=-4*200*u*(1-u),lr=T*u,sq=1-.08*sin(PI*cl((t-.6)/.1))-.05*sin(PI*cl((t-.13)/.08))
|
||||||
|
const sp=t>=.2?1-io((t-.66)/.3):0,up=io((t-.06)/.12)*(1-io((t-.84)/.12))
|
||||||
|
c.strokeStyle=K;c.lineWidth=6
|
||||||
|
const bs=bk((t-.2)/.05)*(1-io((t-.27)/.12))
|
||||||
|
if(bs>.01){c.fillStyle='#ffd43b';star(c,CX,96,92*bs,12,.6,t*2);c.fill();c.stroke();c.fillStyle='#ff922b';star(c,CX,96,56*bs,12,.6,t*2+.2);c.fill()}
|
||||||
|
c.save();c.translate(CX,CY+R);c.scale(2-sq,sq);c.translate(-CX,-CY-R)
|
||||||
|
// brain peeking out while the lid is off
|
||||||
|
if(boom){c.save();c.beginPath();c.arc(CX,CY,R,0,T);c.clip();c.fillStyle=P;c.beginPath();c.ellipse(CX,118,58,30,0,PI,0);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();for(const[x,d]of[[100,1],[128,-1],[156,1]])c.moveTo(x,96),c.quadraticCurveTo(x+10*d,104,x,112);c.stroke();c.restore()}
|
||||||
|
c.save();c.beginPath();zig(c);c.lineTo(230,256);c.lineTo(26,256);c.closePath();if(boom)c.clip()
|
||||||
|
c.fillStyle=H;c.beginPath();c.arc(CX,CY,R,0,T);c.fill();c.lineWidth=6;c.stroke();c.restore()
|
||||||
|
if(boom){c.save();c.beginPath();c.arc(CX,CY,R,0,T);c.clip();c.fillStyle=K;c.beginPath();zig(c);c.lineTo(206,124);c.lineTo(50,124);c.fill();c.restore()
|
||||||
|
c.save();c.beginPath();c.arc(CX,CY,R+3,0,T);c.clip();c.lineWidth=6;c.beginPath();zig(c);c.stroke();c.restore()}
|
||||||
|
// face
|
||||||
|
c.fillStyle=K;c.lineWidth=5
|
||||||
|
for(const d of[-1,1]){const x=CX+d*30,y=152
|
||||||
|
if(dz){c.lineWidth=4;c.beginPath();for(let a=0;a<4*PI;a+=.3){const r=1.3*a;c.lineTo(x+r*cos(d*a+t*20),y+r*sin(d*a+t*20))}c.stroke()}
|
||||||
|
else if(wide>.05){const er=8+14*wide;c.fillStyle='#fff';c.beginPath();c.ellipse(x,y,er,er*1.15,0,0,T);c.fill();c.stroke();c.fillStyle=K;c.beginPath();c.arc(x,y,6-2.5*wide,0,T);c.fill()}
|
||||||
|
else c.beginPath(),c.arc(x,y,7,0,T),c.fill()
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(x-12,y-24-16*wide+(dz?10:0));c.lineTo(x+12,y-24-16*wide+(dz?10:0)-d*4*(1-wide));c.stroke()}
|
||||||
|
c.fillStyle=K;c.beginPath()
|
||||||
|
if(t>=.2&&t<.63)c.ellipse(CX,196,16,20,0,0,T),c.fill(),c.fillStyle='#ff8787',c.beginPath(),c.ellipse(CX,206,9,5,0,0,T),c.fill()
|
||||||
|
else if(dz){c.lineWidth=4;c.moveTo(CX-18,196);for(let k=1;k<=6;k++)c.lineTo(CX-18+6*k,196+(k%2?-4:4));c.stroke()}
|
||||||
|
else c.ellipse(CX,194,8*(1+wide*.4),5+6*wide,0,0,T),c.fill()
|
||||||
|
c.fillStyle='#ffa8a8';for(const d of[-1,1])c.beginPath(),c.ellipse(CX+d*52,180,9,5,0,0,T),c.fill()
|
||||||
|
c.restore()
|
||||||
|
// lid
|
||||||
|
c.save();c.translate(CX,92+ly);c.rotate(lr);c.translate(-CX,-92)
|
||||||
|
c.save();c.beginPath();zig(c);c.lineTo(230,0);c.lineTo(26,0);c.closePath();c.clip();c.fillStyle=H;c.beginPath();c.arc(CX,CY,R,0,T);c.fill();c.lineWidth=6;c.stroke()
|
||||||
|
c.fillStyle=HL;c.beginPath();c.ellipse(96,98,16,9,-.5,0,T);c.fill();c.restore()
|
||||||
|
if(boom){c.save();c.beginPath();c.arc(CX,CY,R+3,0,T);c.clip();c.lineWidth=6;c.beginPath();zig(c);c.stroke();c.restore()}
|
||||||
|
c.restore()
|
||||||
|
hand(c,CX-R+2-14*sp,170-50*up-14*sp,-.4-.7*sp,sp);hand(c,CX+R-2+14*sp,170-50*up-14*sp,.4+.7*sp,sp)
|
||||||
|
if(t>.21&&t<.75)CF.concat(CF).forEach((f,k)=>{const a=-PI/2+(k/11-.5)*2.6,v=.8+.5*((k*7)%5)/5,tau=(t-.2)*v,x=CX+cos(a)*520*tau,y=96+sin(a)*520*tau+900*tau*tau
|
||||||
|
c.save();c.translate(x,y);c.rotate(k+tau*30);c.fillStyle=f;c.lineWidth=3;c.beginPath();c.rect(-7,-4,14,8);c.fill();c.stroke();c.restore()})
|
||||||
|
if(t>=.6&&t<.7){c.lineWidth=5;for(const a of[-.5,0,.5])c.beginPath(),c.moveTo(CX+60*sin(a),72-60*cos(a)+40),c.lineTo(CX+80*sin(a),72-80*cos(a)+40),c.stroke()}
|
||||||
|
if(dz){c.fillStyle='#ffd43b';c.lineWidth=3;for(let k=0;k<3;k++){const a=T*(t*2.5)+k*T/3;star(c,CX+80*cos(a),66+16*sin(a),12,5,.45);c.fill();c.stroke()}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// a literal mood swing: a blob on a playground swing is a beaming sunny yellow on the way forward and a sobbing blue on the way back
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
// frames are spaced by swing speed: dense through the fast bottom of the arc, sparse (and held longer) at the slow ends
|
||||||
|
const N=20,D=2300,PH=(()=>{const M=2000,cum=[0];for(let j=1;j<=M;j++)cum.push(cum[j-1]+abs(cos(T*(j-.5)/M))+.4);return[...Array(N+1)].map((_,k)=>{const g=k/N*cum[M];let j=0;while(j<M&&cum[j+1]<g)j++;return(j+(g-cum[j])/(cum[j+1]-cum[j]))/M})})()
|
||||||
|
export const frames=N,delay=PH.slice(0,N).map((p,k)=>Math.round((PH[k+1]-p)*D)),rim=4
|
||||||
|
const G={M:'0c0056a0ac',O:'2060828a6c2c0a0220',D:'005083895c0c00'," ":'',S:'82602002042666888a6c2c0a',W:'002c558ca0',I:'0040 202c 0c4c',N:'0c008c80',G:'826020020a2c6c8a8656'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const PX=128,PY=24,L=138,A=.62
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=PH[i],f=A*sin(t*T),v=cos(t*T),up=f>0
|
||||||
|
// A-frame seen from the side
|
||||||
|
c.lineWidth=7;for(const[w,s]of[[17,'#111'],[7,'#ff922b']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(30,214),c.lineTo(PX,PY),c.lineTo(226,214),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.fillStyle='#ced4da';c.lineWidth=5;for(const x of[30,226])c.beginPath(),c.ellipse(x,216,16,6,0,0,T),c.fill(),c.stroke()
|
||||||
|
// swing + blob in the rope's frame, seat at the origin
|
||||||
|
c.save();c.translate(PX+L*sin(f),PY+L*cos(f));c.rotate(-f)
|
||||||
|
c.lineWidth=4;c.strokeStyle='#111';c.beginPath();c.moveTo(-8,-L);c.lineTo(-8,0);c.stroke();c.scale(1.3,1.3)
|
||||||
|
// legs kick forward on the way up front, tuck on the way back
|
||||||
|
const lg=up?-.25-.5*f/A:.9+.3*f/A
|
||||||
|
c.lineWidth=6;for(const d of[0,6]){c.save();c.translate(8+d,-6);c.rotate(lg);c.beginPath();c.moveTo(0,0);c.lineTo(18,8);c.stroke();c.fillStyle='#111';c.beginPath();c.ellipse(21,8,6,4.5,.3,0,T);c.fill();c.restore()}
|
||||||
|
c.fillStyle='#a9784f';c.lineWidth=5;c.beginPath();c.roundRect(-26,-4,52,9,4);c.fill();c.stroke()
|
||||||
|
c.fillStyle=up?'#ffe066':'#91a7ff';c.lineWidth=6;c.beginPath();c.moveTo(-30,-4);c.bezierCurveTo(-34,-44,-18,-62,0,-62);c.bezierCurveTo(22,-62,34,-44,30,-4);c.closePath();c.fill();c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(-2,-62);c.quadraticCurveTo(-4,-76,8,-76);c.quadraticCurveTo(14,-70,6,-66);c.stroke()
|
||||||
|
c.fillStyle=up?'#ffe066':'#91a7ff';c.lineWidth=4;c.beginPath();c.arc(-4,-30,6.5,0,T);c.fill();c.stroke()
|
||||||
|
// faces, looking forward (+x)
|
||||||
|
c.lineWidth=4.5;c.strokeStyle='#111'
|
||||||
|
if(up){
|
||||||
|
for(const x of[4,22])c.beginPath(),c.arc(x,-38,6,PI*1.1,PI*1.9),c.stroke()
|
||||||
|
c.fillStyle='#ff8787';for(const x of[-6,30])c.beginPath(),c.ellipse(x,-28,5,3.5,0,0,T),c.fill()
|
||||||
|
c.fillStyle='#862e2e';c.lineWidth=4;c.beginPath();c.moveTo(2,-26);c.lineTo(26,-26);c.quadraticCurveTo(24,-10,14,-10);c.quadraticCurveTo(4,-10,2,-26);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ff8787';c.beginPath();c.ellipse(14,-13,6,3,0,PI,0);c.fill()
|
||||||
|
}else{
|
||||||
|
c.lineWidth=4;for(const x of[3,23])c.beginPath(),c.moveTo(x-6,-42),c.quadraticCurveTo(x,-34,x+6,-42),c.stroke()
|
||||||
|
for(const[w,s]of[[8,'#111'],[4,'#74c0fc']]){c.lineWidth=w;c.strokeStyle=s;for(const x of[3,23])c.beginPath(),c.moveTo(x,-37),c.quadraticCurveTo(x-2,-26,x+1,-12),c.stroke()}
|
||||||
|
c.strokeStyle='#111';c.fillStyle='#862e2e';c.lineWidth=4;c.beginPath();c.moveTo(7,-14);c.quadraticCurveTo(13,-28,19,-14);c.quadraticCurveTo(13,-18,7,-14);c.fill();c.stroke()
|
||||||
|
// tears blown off behind
|
||||||
|
c.fillStyle='#74c0fc';c.lineWidth=3;for(const[x,y,s]of[[-14,-42,1],[-30,-34,.8],[-44,-46,.6]]){const dx=x-6*abs(v),dy=y+4*sin(t*T*3+x);c.beginPath();c.ellipse(dx,dy,7*s,4.5*s,0,0,T);c.fill();c.stroke()}
|
||||||
|
}
|
||||||
|
c.restore()
|
||||||
|
// pivot cap
|
||||||
|
c.fillStyle='#ced4da';c.lineWidth=5;c.beginPath();c.arc(PX,PY,9,0,T);c.fill();c.stroke()
|
||||||
|
txt(c,'MOOD SWINGS',128,238,18,'#fff')
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
// video call tile where someone is passionately going "blah blah blah" and wagging a finger, while their red muted mic pulses in the corner
|
||||||
|
const{sin,cos,PI,abs,min,max}=Math,T=2*PI
|
||||||
|
export const frames=16,delay=Array(16).fill(85),rim=4
|
||||||
|
const G={B:'M0 3L0 0L2.3 0Q3.7 0 3.7 1.5Q3.7 3 2.3 3L0 3L0 6L2.5 6Q4 6 4 4.5Q4 3 2.3 3',L:'M0 0L0 6L4 6',A:'M0 6L2 0L4 6M.7 4L3.3 4',H:'M0 0L0 6M4 0L4 6M0 3L4 3'}
|
||||||
|
const txt=(c,s,x,y,k,w)=>{
|
||||||
|
const a=5.4*k,W=s.length*a-1.4*k;c.beginPath()
|
||||||
|
;[...s].forEach((ch,j)=>{const ox=x-W/2+j*a;for(const[,o,q]of(G[ch]||'').matchAll(/([MLQ])([^MLQ]*)/g)){const n=q.trim().split(/[ ,]+/).map((v,m)=>m%2?y+v*k:ox+v*k);o=='M'?c.moveTo(...n):o=='L'?c.lineTo(...n):c.quadraticCurveTo(...n)}})
|
||||||
|
c.lineWidth=w;c.stroke()
|
||||||
|
}
|
||||||
|
const BG='#343a40',SK='#ffd8b5',HA='#5c3a21',SH='#20c997',HX=156,HY=122
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const m=[.2,1,.5,.9,.1,.8,.4,1][i%8],nod=[0,2,0,-1][i%4],ch=sin(T*t*4)
|
||||||
|
c.fillStyle=BG;c.beginPath();c.roundRect(8,22,240,206,20);c.fill();c.stroke()
|
||||||
|
c.save();c.beginPath();c.roundRect(8,22,240,206,20);c.clip()
|
||||||
|
// shoulders and shirt
|
||||||
|
c.fillStyle=SH;c.beginPath();c.moveTo(78,232);c.quadraticCurveTo(80,182,120,176);c.lineTo(192,176);c.quadraticCurveTo(232,182,236,232);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SK;c.lineWidth=6;c.beginPath();c.moveTo(144,160);c.lineTo(144,180);c.quadraticCurveTo(156,190,168,180);c.lineTo(168,160);c.fill();c.stroke()
|
||||||
|
// chopping hand
|
||||||
|
const hx=222,hy=168-ch*16
|
||||||
|
c.fillStyle=SH;c.lineWidth=7;c.beginPath();c.moveTo(214,232);c.lineTo(hx-6,hy+26);c.lineTo(hx+14,hy+30);c.lineTo(242,232);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SK;c.save();c.translate(hx,hy);c.rotate(-.2+ch*.25);c.lineWidth=6;c.beginPath();c.roundRect(-4,-46,13,40,6.5);c.fill();c.stroke();c.lineWidth=7;c.beginPath();c.roundRect(-16,-14,34,32,12);c.fill();c.stroke();c.lineWidth=4;c.beginPath();c.moveTo(-10,-2);c.lineTo(6,-2);c.moveTo(-10,8);c.lineTo(8,8);c.stroke();c.restore()
|
||||||
|
c.restore()
|
||||||
|
// head
|
||||||
|
c.save();c.translate(0,nod);c.fillStyle=SK;c.lineWidth=7;c.beginPath();c.arc(HX,HY,38,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HA;c.beginPath();c.moveTo(HX-40,HY-2);c.quadraticCurveTo(HX-44,HY-44,HX,HY-44);c.quadraticCurveTo(HX+44,HY-44,HX+40,HY-2);c.quadraticCurveTo(HX+28,HY-26,HX+4,HY-24);c.quadraticCurveTo(HX-26,HY-22,HX-40,HY-2);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(HX+d*14,HY+2,4.5,0,T),c.fill()
|
||||||
|
c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.moveTo(HX+d*8,HY-10-m*3+d*2),c.lineTo(HX+d*21,HY-12-m*3-d*2),c.stroke()
|
||||||
|
c.fillStyle='#c92a2a';c.lineWidth=4;c.beginPath();c.ellipse(HX,HY+20,9,2+m*8,0,0,T);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// speech bubble filling up with blah
|
||||||
|
const n=min(4,1+(t*5|0))
|
||||||
|
c.fillStyle='#fff';c.lineWidth=6;c.beginPath();c.moveTo(96,92);c.lineTo(122,118);c.lineTo(84,96);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(14,34,118,66,16);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.moveTo(94,94);c.lineTo(110,108);c.lineTo(86,96);c.fill()
|
||||||
|
c.strokeStyle='#111';for(let k=0;k<n;k++)txt(c,'BLAH',k%2?102:44,k<2?44:70,2,4.5)
|
||||||
|
// muted mic, pulsing
|
||||||
|
const MX=46,MY=192,p=t*2%1
|
||||||
|
c.strokeStyle='#ff8787';c.lineWidth=7*(1-p)+1;c.beginPath();c.arc(MX,MY,26+p*18,0,T);c.stroke();c.strokeStyle='#111'
|
||||||
|
c.fillStyle='#fa5252';c.lineWidth=6;c.beginPath();c.arc(MX,MY,26,0,T);c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#fff';c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.roundRect(MX-6,MY-16,12,20,6);c.fill();c.beginPath();c.arc(MX,MY-4,11,.1*PI,.9*PI);c.moveTo(MX,MY+7);c.lineTo(MX,MY+14);c.moveTo(MX-6,MY+14);c.lineTo(MX+6,MY+14);c.stroke()
|
||||||
|
c.strokeStyle='#fa5252';c.lineWidth=9;c.beginPath();c.moveTo(MX-15,MY-15);c.lineTo(MX+15,MY+15);c.stroke();c.strokeStyle='#fff';c.lineWidth=4;c.stroke();c.strokeStyle='#111'
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// a turtle pokes its head out, spots something off screen, NOPE pops up and it slams back into its shell to shiver
|
||||||
|
import{Path2D}from'@napi-rs/canvas'
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
const U=[.03,.08,.13,.18,.23,.27,.33,.385,.42,.46,.5,.56,.62,.66,.7,.75,.8,.88,.92,.97]
|
||||||
|
export const frames=U.length,delay=[80,80,80,120,120,120,450,50,60,60,60,70,70,70,70,70,70,80,80,350],rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u*u*(3-2*u)),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||||
|
const K='#1b1b1f',G='#8ce99a',D='#2f9e44',S='#51cf66',Y='#ffe066'
|
||||||
|
const F={N:'M0 10V0L6 10V0',O:'M3 0A3 5 0 1 1 3 10A3 5 0 1 1 3 0Z',P:'M0 10V0H3A2.75 2.75 0 0 1 3 5.5H0',E:'M6 0H0V10H6M0 5H4.5'}
|
||||||
|
const L=(c,ch,x,y,s,a)=>{c.save();c.translate(x,y);c.rotate(a);c.scale(s*4.8,s*4.8);c.translate(-3,-5);for(const[w,st]of[[5.6,K],[2.4,'#ff6b6b']])c.lineWidth=w,c.strokeStyle=st,c.stroke(new Path2D(F[ch]));c.restore()}
|
||||||
|
const dome=c=>{c.beginPath();c.moveTo(26,198);c.bezierCurveTo(26,124,72,100,106,100);c.bezierCurveTo(140,100,186,124,186,198);c.closePath()}
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=U[i]
|
||||||
|
const out=io(t/.16)*(1-cl((t-.37)/.035)),lg=io(t/.1)*(1-cl((t-.37)/.03)),wide=t>.29&&t<.4
|
||||||
|
const sv=t>.4&&t<.9?2.5*(1-io((t-.7)/.2)):0,jx=t<.6?sv*(i%2?1:-1):0,ex=sv*(i%2?.6:-.6),sq=1-.1*sin(PI*cl((t-.38)/.08))
|
||||||
|
c.save();c.translate(106+jx,214);c.scale(2-sq,sq);c.translate(-106,-214)
|
||||||
|
c.lineWidth=6
|
||||||
|
for(const[x,f]of[[52,D],[92,D],[124,S],[164,S]]){c.fillStyle=f;c.beginPath();c.roundRect(x-14,186,28,10+24*lg,13);c.fill();c.stroke()}
|
||||||
|
c.fillStyle=S;c.beginPath();c.moveTo(30,190);c.lineTo(10-8*lg,200);c.lineTo(32,204);c.fill();c.stroke()
|
||||||
|
const hx=160+62*out,hy=180-38*out
|
||||||
|
for(const[w,s]of[[36,K],[24,S]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(160,190),c.quadraticCurveTo(hx-20,192,hx,hy),c.stroke()
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle=S;c.beginPath();c.ellipse(hx,hy,30,26,-.1,0,T);c.fill();c.stroke()
|
||||||
|
const er=wide?13:10,pr=wide?3.5:5.5,lk=t<.29?3*sin(T*cl((t-.12)/.17)):0
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(hx+6,hy-7,er,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=K;c.beginPath();c.arc(hx+9+lk,hy-6,pr,0,T);c.fill()
|
||||||
|
if(!wide){c.fillStyle=S;c.beginPath();c.arc(hx+6,hy-7,er+1.5,PI,0);c.lineTo(hx+6+er+1.5,hy-9);c.lineTo(hx+6-er-1.5,hy-9);c.fill();c.lineWidth=4;c.beginPath();c.moveTo(hx-6,hy-9);c.lineTo(hx+18,hy-9);c.stroke()}
|
||||||
|
c.lineWidth=4;c.beginPath();wide?c.ellipse(hx+19,hy+11,4,5,0,0,T):c.arc(hx+13,hy+4,8,.25*PI,.7*PI);c.stroke()
|
||||||
|
c.fillStyle='#ffa8a8';c.beginPath();c.ellipse(hx-6,hy+9,6,3.5,0,0,T);c.fill()
|
||||||
|
c.lineWidth=6;dome(c);c.fillStyle=G;c.fill();c.save();c.clip()
|
||||||
|
c.strokeStyle=D;c.lineWidth=5;c.beginPath();for(let k=0;k<6;k++){const a=k*PI/3+PI/6;c.lineTo(106+30*cos(a),150+24*sin(a))}c.closePath()
|
||||||
|
for(let k=0;k<6;k++){const a=k*PI/3+PI/6;c.moveTo(106+30*cos(a),150+24*sin(a));c.lineTo(106+80*cos(a),150+66*sin(a))}c.stroke()
|
||||||
|
c.restore();c.lineWidth=6;dome(c);c.stroke()
|
||||||
|
c.fillStyle=Y;c.beginPath();c.roundRect(18,188,180,20,10);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.ellipse(80,120,14,7,-.45,0,T);c.fill()
|
||||||
|
if(out<.05){
|
||||||
|
c.fillStyle=K;c.beginPath();c.ellipse(176,170,13,19,0,0,T);c.fill()
|
||||||
|
if(t>.46){c.fillStyle='#fff';for(const d of[-5.5,5.5])c.beginPath(),c.arc(177+d+ex,166,4,0,T),c.fill()}
|
||||||
|
}
|
||||||
|
c.restore()
|
||||||
|
if(wide){c.strokeStyle=K;c.fillStyle='#ff6b6b';c.lineWidth=5;c.beginPath();c.roundRect(hx+8,hy-96,18,42,9);c.fill();c.stroke();c.beginPath();c.arc(hx+17,hy-38,9,0,T);c.fill();c.stroke()}
|
||||||
|
if(sv>.3&&t>=.6){c.strokeStyle=K;c.lineWidth=4;for(const d of[-1,1])for(const k of[0,1])c.beginPath(),c.arc(106,150,104+k*12+(i%2)*3,d>0?-.35:PI-.35,d>0?.35:PI+.35),c.stroke()}
|
||||||
|
if(sv>.3){c.fillStyle='#74c0fc';c.strokeStyle=K;c.lineWidth=3;for(const[x,d]of[[60,-1],[150,1]]){const u=(t*6+(d>0?.5:0))%1;c.save();c.translate(x+d*28*u,108-26*sin(PI*u)+20*u);c.rotate(d*.6);c.beginPath();c.moveTo(0,-10);c.quadraticCurveTo(8,2,0,6);c.quadraticCurveTo(-8,2,0,-10);c.fill();c.stroke();c.restore()}}
|
||||||
|
;[...'NOPE'].forEach((ch,k)=>{const s=bk((t-.4-k*.045)/.08)*(1-io((t-.86)/.08));if(s>.01)L(c,ch,53+k*50,50,s,(k%2?.12:-.12))})
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// judgy half-lidded blob scribbles in a little notepad, taps a period, NOTED. pops up over its head, then it flips to a fresh page
|
||||||
|
const{sin,cos,PI,max,min,floor}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=80,rim=5
|
||||||
|
const Y='#ffd43b',BL='#ff8787',PD='#fff',LN='#a5d8ff',PN='#ffd43b',ER='#f783ac',INK='#364fc7'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const G={N:[[0,6,0,0,4,6,4,0]],O:[[2,0,3.4,.6,4,2,4,4,3.4,5.4,2,6,.6,5.4,0,4,0,2,.6,.6,2,0]],T:[[0,0,4,0],[2,0,2,6]],E:[[4,0,0,0,0,6,4,6],[0,3,3.2,3]],D:[[0,0,0,6,2,6,3.6,5.2,4,3,3.6,.8,2,0,0,0]],'.':[[0,6,0,6]]}
|
||||||
|
const word=(c,s,h,col)=>{
|
||||||
|
const k=h/6,adv=s.split('').map(ch=>ch=='.'?2:6.2),W=(adv.reduce((a,b)=>a+b)-2)*k
|
||||||
|
for(const[w,st]of[[h*.5,'#111'],[h*.25,col]]){c.lineWidth=w;c.strokeStyle=st;let x=-W/2;c.beginPath()
|
||||||
|
s.split('').forEach((ch,j)=>{for(const p of G[ch]){c.moveTo(x+p[0]*k,p[1]*k-h/2);for(let q=2;q<p.length;q+=2)c.lineTo(x+p[q]*k,p[q+1]*k-h/2)}x+=adv[j]*k})
|
||||||
|
c.stroke()}
|
||||||
|
c.strokeStyle='#111'}
|
||||||
|
// scribble path for line r, u in [0,1]
|
||||||
|
const sc=(r,u)=>[-24+u*48,-14+r*14+3*sin(u*30+r)-2*cos(u*47)]
|
||||||
|
export default(c,t)=>{
|
||||||
|
const wr=min(1,t/.48),tap=t>=.5&&t<.56,up=t>=.56&&t<.92,flip=ez(t,.88,.98),pop=ez(t,.56,.62),bump=1+.3*sin(ez(t,.56,.68)*PI)
|
||||||
|
// body
|
||||||
|
c.fillStyle=Y;c.beginPath();c.moveTo(34,240);c.bezierCurveTo(28,130,56,84,110,84);c.bezierCurveTo(164,84,192,130,186,240);c.closePath();c.fill();c.stroke()
|
||||||
|
// face: half-lidded eyes, one brow up
|
||||||
|
const lx=up?7:-2,ly=up?0:5
|
||||||
|
for(const d of[-1,1]){const x=110+d*26,y=134
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4.5;c.beginPath();c.ellipse(x,y,14,12,0,0,T);c.fill()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.arc(x+lx,y+ly,5.5,0,T);c.fill()
|
||||||
|
c.fillStyle=Y;c.beginPath();c.rect(x-16,y-14,32,12);c.fill()
|
||||||
|
c.beginPath();c.ellipse(x,y,14,12,0,0,T);c.stroke()
|
||||||
|
c.lineWidth=5.5;c.beginPath();c.moveTo(x-15,y-2);c.lineTo(x+15,y-2);c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();const by=d>0&&up?y-30-4*pop:y-22;c.moveTo(x-12,by+(d>0&&up?4:0));c.quadraticCurveTo(x,by-4,x+12,by);c.stroke()}
|
||||||
|
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(110+d*44,160,10,5,0,0,T),c.fill()
|
||||||
|
c.lineWidth=4.5;c.beginPath();c.moveTo(100,170);c.quadraticCurveTo(112,172,122,166);c.stroke()
|
||||||
|
// notepad, the page flips over the spiral to the back when it's done
|
||||||
|
const th=flip*1.5*PI,pg=(ink,back)=>{c.fillStyle=back?'#e9ecef':PD;c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.roundRect(-34,-30,68,62,5);c.fill();c.stroke();if(back)return
|
||||||
|
c.strokeStyle=LN;c.lineWidth=2.5;c.beginPath();for(let r=0;r<3;r++)c.moveTo(-28,-8+r*14),c.lineTo(28,-8+r*14);c.stroke()
|
||||||
|
if(ink){c.strokeStyle=INK;c.lineWidth=3;c.beginPath();for(let r=0;r<3;r++){const e=min(1,max(0,wr*3-r));if(e>0)for(let u=0;u<=e;u+=.04){const[x,y]=sc(r,u);u?c.lineTo(x,y):c.moveTo(x,y)}}c.stroke()
|
||||||
|
if(t>=.52){c.fillStyle=INK;c.beginPath();c.arc(26,14,3.5,0,T);c.fill()}}
|
||||||
|
c.strokeStyle='#111'}
|
||||||
|
const fp=()=>{c.save();c.translate(0,-30);c.scale(1,cos(th));c.translate(0,30);pg(1,cos(th)<0);c.restore()}
|
||||||
|
c.save();c.translate(168,196);c.rotate(-.12)
|
||||||
|
if(flip>0&&th>PI)fp()
|
||||||
|
pg(!flip,0)
|
||||||
|
if(flip>0&&th<=PI)fp()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=4;for(let k=-2;k<=2;k++)c.beginPath(),c.arc(k*13,-30,5,PI,0),c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// hand holding the pad
|
||||||
|
c.fillStyle=Y;c.lineWidth=6;c.beginPath();c.ellipse(136,222,14,12,0,0,T);c.fill();c.stroke()
|
||||||
|
// pencil hand
|
||||||
|
let px,py
|
||||||
|
if(t<.5){const r=min(2,floor(wr*3)),[x,y]=sc(r,wr*3-r);px=x;py=y}else[px,py]=[26,14]
|
||||||
|
const q=[168+px*cos(-.12)-py*sin(-.12),196+px*sin(-.12)+py*cos(-.12)-(tap?0:t>=.5?8+10*ez(t,.56,.66):0)]
|
||||||
|
c.save();c.translate(q[0],q[1]);c.rotate(.55)
|
||||||
|
c.lineWidth=5;c.fillStyle='#ffe8cc';c.beginPath();c.moveTo(0,0);c.lineTo(-6,-14);c.lineTo(6,-14);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.moveTo(0,0);c.lineTo(-2.5,-6);c.lineTo(2.5,-6);c.closePath();c.fill()
|
||||||
|
c.fillStyle=PN;c.beginPath();c.roundRect(-6,-58,12,44,2);c.fill();c.stroke()
|
||||||
|
c.fillStyle=ER;c.beginPath();c.roundRect(-6,-70,12,12,[4,4,0,0]);c.fill();c.stroke()
|
||||||
|
c.fillStyle=Y;c.lineWidth=6;c.beginPath();c.ellipse(4,-30,13,12,0,0,T);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// NOTED.
|
||||||
|
if(up||t>=.92&&t<.96){const s=pop*bump*(t>=.88?1-ez(t,.88,.94):1);if(s>.05){c.save();c.translate(124,40);c.rotate(-.06);c.scale(s,s);word(c,'NOTED.',34,'#fff');c.restore()}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// pink brain sprinting flat out in a hamster wheel under the moon, wide eyed and sweating, question marks popping off it
|
||||||
|
const{sin,cos,PI,max,min,abs}=Math,T=2*PI
|
||||||
|
export const frames=12,delay=80,rim=5
|
||||||
|
const PK='#faa2c1',PD='#e64980',MT='#ced4da',MD='#868e96',SW='#74c0fc',MN='#ffe066'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const CL=[[-26,-6,20],[-6,-16,22],[18,-12,21],[30,6,17],[-30,12,16],[-10,10,20],[14,12,19]]
|
||||||
|
const qm=(c,x,y,s,a)=>{c.save();c.translate(x,y);c.rotate(a);c.scale(s,s)
|
||||||
|
for(const[w,st]of[[13,'#111'],[6,'#fff']]){c.lineWidth=w;c.strokeStyle=st;c.beginPath();c.arc(0,-8,8,-PI*.95,PI*.35);c.lineTo(0,6);c.moveTo(0,15);c.lineTo(0,15);c.stroke()}
|
||||||
|
c.restore();c.strokeStyle='#111'}
|
||||||
|
export default(c,t)=>{
|
||||||
|
const rot=t*T/3,ph=t*T*3,bob=abs(sin(ph))*-6,X=126,Y=158+bob
|
||||||
|
// moon + stars
|
||||||
|
c.fillStyle=MN;c.lineWidth=5;c.beginPath();c.arc(34,34,22,.6,-2.4+T,false);c.arc(46,24,18,-2.1+T,1.05,true);c.closePath();c.fill();c.stroke()
|
||||||
|
for(const[x,y,s]of[[226,24,7],[206,48,5],[70,14,4]]){c.fillStyle='#fff';c.lineWidth=3.5;c.beginPath();for(let k=0;k<8;k++){const r=k%2?s*.35:s,a=k*PI/4;c.lineTo(x+cos(a)*r,y+sin(a)*r)}c.closePath();c.fill();c.stroke()}
|
||||||
|
// stand back leg
|
||||||
|
c.lineWidth=12;c.strokeStyle='#111';c.beginPath();c.moveTo(128,128);c.lineTo(62,240);c.moveTo(128,128);c.lineTo(194,240);c.stroke()
|
||||||
|
c.lineWidth=5;c.strokeStyle=MD;c.stroke();c.strokeStyle='#111'
|
||||||
|
// wheel: spokes turning, rim
|
||||||
|
c.lineWidth=5;c.beginPath();for(let k=0;k<6;k++){const a=rot+k*PI/3;c.moveTo(128+cos(a)*12,128+sin(a)*12);c.lineTo(128+cos(a)*86,128+sin(a)*86)}c.stroke()
|
||||||
|
for(const r of[86,104]){for(const[w,s]of[[11,'#111'],[4,MT]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(128,128,r,0,T),c.stroke()}
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=MT;c.beginPath();c.arc(128,128,13,0,T);c.fill();c.stroke()
|
||||||
|
// legs: feet planted on the wheel floor, pushing backwards
|
||||||
|
for(const o of[0,PI]){const a=ph+o,hx=X+(o?-8:8),fx=X+(o?-8:8)+18*cos(a),fy=210-max(0,sin(a))*14
|
||||||
|
c.lineWidth=6;c.beginPath();c.moveTo(hx,Y+20);c.lineTo((hx+fx)/2+6,(Y+20+fy)/2);c.lineTo(fx,fy);c.stroke()
|
||||||
|
c.fillStyle=o?'#ff6b6b':'#fa5252';c.lineWidth=4.5;c.beginPath();c.ellipse(fx+5,fy+1,10,6,0,0,T);c.fill();c.stroke()}
|
||||||
|
// brain
|
||||||
|
c.save();c.translate(X,Y);c.rotate(.12)
|
||||||
|
c.lineWidth=14;for(const[x,y,r]of CL)c.beginPath(),c.arc(x,y,r,0,T),c.stroke()
|
||||||
|
c.fillStyle=PK;for(const[x,y,r]of CL)c.beginPath(),c.arc(x,y,r,0,T),c.fill()
|
||||||
|
c.strokeStyle=PD;c.lineWidth=4;c.beginPath();c.moveTo(4,-34);c.bezierCurveTo(-4,-22,10,-14,2,-4)
|
||||||
|
c.moveTo(-30,-14);c.quadraticCurveTo(-22,-20,-18,-10);c.moveTo(22,-24);c.quadraticCurveTo(30,-16,24,-8);c.moveTo(34,14);c.quadraticCurveTo(28,20,36,26);c.moveTo(-36,20);c.quadraticCurveTo(-28,22,-26,30);c.stroke()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
for(const d of[-1,1]){const x=6+d*14,y=6
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.ellipse(x,y,10,12,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.arc(x+3,y,3.4,0,T);c.fill()}
|
||||||
|
c.fillStyle='#c92a2a';c.lineWidth=4;c.beginPath();c.ellipse(10,28,6,4+2*abs(sin(ph)),0,0,T);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// sweat flying off the back
|
||||||
|
for(let k=0;k<3;k++){const p=(t*3+k/3)%1,x=X-34-p*44,y=Y-28-p*30+p*p*60,z=1-p*.7;if(p<.85)c.fillStyle=SW,c.lineWidth=3.5,c.beginPath(),c.moveTo(x,y-8*z),c.quadraticCurveTo(x+6*z,y,x,y+4*z),c.quadraticCurveTo(x-6*z,y,x,y-8*z),c.fill(),c.stroke()}
|
||||||
|
// ?s popping off the top
|
||||||
|
for(let k=0;k<2;k++){const p=(t*2+k/2)%1,s=ez(p,0,.15)*(1-ez(p,.75,1));if(s>.05)qm(c,X+(k?24:-8)+p*10*(k?1:-1),Y-56-p*30,s,(k?.25:-.2))}
|
||||||
|
// front leg of stand
|
||||||
|
c.lineWidth=12;c.beginPath();c.moveTo(40,240);c.lineTo(216,240);c.stroke();c.lineWidth=5;c.strokeStyle=MD;c.stroke();c.strokeStyle='#111'
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
// an invite slides in and the little guy in pajamas dreads it, then a CANCELLED stamp slams down and he breaks into a happy dance
|
||||||
|
import{Path2D}from'@napi-rs/canvas'
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
const U=[.04,.1,.23,.26,.3,...Array.from({length:8},(_,k)=>.34+k*.0625),.86,.92]
|
||||||
|
export const frames=U.length,delay=[80,600,90,80,300,...Array(8).fill(95),95,80],rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u*u*(3-2*u)),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||||
|
const K='#1b1b1f',RD='#e03131',PJ='#a5d8ff'
|
||||||
|
const F={C:'M5.3 1.8A3 5 0 1 0 5.3 8.2',A:'M0 10L3 0L6 10M1 6.5H5',N:'M0 10V0L6 10V0',E:'M6 0H0V10H6M0 5H4.5',L:'M0 0V10H6',D:'M0 0V10H1.5A4.5 5 0 0 0 1.5 0Z'}
|
||||||
|
const note=(c,x,y,a)=>{c.save();c.translate(x,y);c.rotate(a);c.fillStyle=K;c.strokeStyle=K;c.lineWidth=4;c.beginPath();c.ellipse(0,0,7,5,-.4,0,T);c.fill();c.beginPath();c.moveTo(6,-2);c.lineTo(6,-24);c.quadraticCurveTo(14,-18,16,-10);c.stroke();c.restore()}
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=U[i],cin=bk(t/.1),st=t>=.2,sl=io((t-.2)/.03),jolt=t>=.23&&t<.3?.04*(i%2?1:-1):0,off=io((t-.86)/.1)
|
||||||
|
const dance=t>=.32&&t<.95,dp=T*(t-.34)/.25,dw=dance?1-off*.6:0,happy=t>=.25
|
||||||
|
// the invite card
|
||||||
|
c.save();c.translate(128+150*off,-120*(1-cin)-30*off+58);c.rotate(jolt+.5*off);c.translate(-128,-58)
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle='#fff';c.beginPath();c.roundRect(22,12,212,96,12);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ff8787';c.beginPath();c.roundRect(22,12,212,26,[12,12,0,0]);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ced4da';for(const[y,w]of[[56,120],[72,96],[88,110]])c.beginPath(),c.roundRect(84,y-4,w,9,4),c.fill()
|
||||||
|
c.fillStyle='#ffd43b';c.lineWidth=4;c.beginPath();c.ellipse(52,66,15,18,0,0,T);c.fill();c.stroke();c.beginPath();c.moveTo(52,84);c.quadraticCurveTo(46,92,54,100);c.stroke()
|
||||||
|
if(st){const s=1+1.4*(1-sl);c.save();c.translate(128,62);c.rotate(-.13);c.scale(s,s);c.globalAlpha=sl
|
||||||
|
c.strokeStyle=RD;c.lineWidth=5;c.beginPath();c.roundRect(-104,-26,208,52,8);c.stroke();c.lineWidth=2.5;c.beginPath();c.roundRect(-97,-19,194,38,5);c.stroke()
|
||||||
|
c.scale(2.5,2.5);c.translate(-35.6,-5);c.lineWidth=2.1;let x=0;for(const ch of'CANCELLED')c.save(),c.translate(x,0),c.stroke(new Path2D(F[ch])),c.restore(),x+=7.9
|
||||||
|
c.restore()}
|
||||||
|
c.restore()
|
||||||
|
if(t>=.22&&t<.3){c.strokeStyle=K;c.lineWidth=5;for(const[x,y,a]of[[14,80,PI],[242,40,0],[242,86,.3],[14,34,PI-.3]])c.beginPath(),c.moveTo(x,y),c.lineTo(x+12*cos(a),y+12*sin(a)),c.stroke()}
|
||||||
|
// pajama guy
|
||||||
|
const sw=dw*sin(dp),hop=dw*abs(sin(dp)),lean=.14*sw
|
||||||
|
c.save();c.translate(128+12*sw,244-14*hop);c.rotate(lean);c.translate(-128,-244)
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle=PJ
|
||||||
|
for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*20,238-(dance&&d*sw>.3?6:0),14,9,0,0,T),c.fill(),c.stroke()
|
||||||
|
const arms=happy?[[90,190,58,148-18*sw*(dance?1:0)],[166,190,198,148+18*sw*(dance?1:0)]]:[[90,192,80,228],[166,192,176,228]]
|
||||||
|
for(const[sx,sy,hx,hy]of arms){for(const[w,s]of[[20,K],[9,PJ]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(sx,sy),c.lineTo(hx,hy),c.stroke()
|
||||||
|
c.strokeStyle=K;c.fillStyle='#ffe8cc';c.lineWidth=5;c.beginPath();c.arc(hx,hy,10,0,T);c.fill();c.stroke()}
|
||||||
|
c.lineWidth=6;c.fillStyle=PJ;c.beginPath();c.ellipse(128,194,46,46,0,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.clip();c.fillStyle='#74c0fc';for(const[x,y]of[[96,214],[150,226],[160,176],[118,236],[88,182]])c.beginPath(),c.arc(x,y,5,0,T),c.fill();c.restore()
|
||||||
|
c.fillStyle='#ffe8cc';c.beginPath();c.ellipse(128,184,34,26,0,0,T);c.fill();c.lineWidth=5;c.stroke()
|
||||||
|
// nightcap flops with the dance
|
||||||
|
const cf=happy?-sw*.5:0;c.fillStyle='#4dabf7';c.lineWidth=6;c.beginPath();c.moveTo(90,162);c.quadraticCurveTo(110,108,150+40*cf,118+16*abs(cf));c.quadraticCurveTo(160,134,166,162);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.roundRect(86,152,84,16,8);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ffd43b';c.lineWidth=5;c.beginPath();c.arc(152+40*cf,120+16*abs(cf),10,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=K;c.lineWidth=4
|
||||||
|
if(!happy){for(const d of[-1,1])c.beginPath(),c.arc(128+d*13,184,6,PI*.1,PI*.9),c.stroke(),c.beginPath(),c.moveTo(128+d*7,172),c.lineTo(128+d*21,176),c.stroke()
|
||||||
|
c.beginPath();c.moveTo(116,200);for(let k=1;k<=4;k++)c.lineTo(116+6*k,200+(k%2?-3:3));c.stroke()
|
||||||
|
c.fillStyle='#74c0fc';c.lineWidth=3;c.beginPath();c.moveTo(166,160);c.quadraticCurveTo(175,176,166,180);c.quadraticCurveTo(157,176,166,160);c.fill();c.stroke()}
|
||||||
|
else if(!dance){c.fillStyle='#ffd43b';c.lineWidth=3;for(const d of[-1,1]){c.beginPath();for(let k=0;k<8;k++){const r=k%2?3:9,a=k*PI/4;c.lineTo(128+d*14+r*cos(a),182+r*sin(a))}c.closePath();c.fill();c.stroke()}
|
||||||
|
c.fillStyle=K;c.beginPath();c.ellipse(128,200,7,8,0,0,T);c.fill()}
|
||||||
|
else{for(const d of[-1,1])c.beginPath(),c.arc(128+d*13,186,6,PI*1.1,PI*1.9),c.stroke()
|
||||||
|
c.beginPath();c.moveTo(116,194);c.quadraticCurveTo(128,193,140,194);c.quadraticCurveTo(138,208,128,208);c.quadraticCurveTo(118,208,116,194);c.fill()}
|
||||||
|
c.fillStyle='#ffa8a8';for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*25,196,6,4,0,0,T),c.fill()
|
||||||
|
c.restore()
|
||||||
|
if(dance){for(const[k,x]of[[0,34],[1,222]]){const u=((t-.34)*2+k*.5)%1;if(u<.9)note(c,x+10*sin(u*T),210-70*u,.3*sin(u*T+k))}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
// progress bar stuck at 99%, the green fill gritting its teeth and straining at the last bit while the time left keeps getting longer
|
||||||
|
const{sin,PI,max,min}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=Array(24).fill(90),rim=4
|
||||||
|
const G={9:'M4 2Q4 0 2 0Q0 0 0 2Q0 3.7 2 3.7Q4 3.7 4 2L4 4Q4 6 2 6Q.9 6 .3 5.3','%':'M4 0L0 6M1 0Q0 0 0 1Q0 2 1 2Q2 2 2 1Q2 0 1 0M3 4Q2 4 2 5Q2 6 3 6Q4 6 4 5Q4 4 3 4',1:'M.8 1.2L2.2 0L2.2 6',4:'M3 6L3 0L0 4.2L4 4.2',3:'M.2 .6Q.9 0 2 0Q3.8 0 3.8 1.5Q3.8 3 1.8 3Q4 3 4 4.5Q4 6 2 6Q.8 6 0 5.3',S:'M3.8 .9Q3.1 0 2 0Q.2 0 .2 1.5Q.2 2.8 2 3Q3.9 3.2 3.9 4.5Q3.9 6 2 6Q.7 6 0 5.1',E:'M4 0L0 0L0 6L4 6M0 3L3.2 3',C:'M4 .9Q3.3 0 2.1 0Q0 0 0 3Q0 6 2.1 6Q3.3 6 4 5.1',M:'M0 6L0 0L2 3.6L4 0L4 6',I:'M2 0L2 6M.8 0L3.2 0M.8 6L3.2 6',N:'M0 6L0 0L4 6L4 0',H:'M0 0L0 6M4 0L4 6M0 3L4 3',R:'M0 6L0 0L2.3 0Q4 0 4 1.7Q4 3.4 2.3 3.4L0 3.4M2 3.4L4 6',D:'M0 0L0 6L1.7 6Q4 6 4 3Q4 0 1.7 0L0 0',A:'M0 6L2 0L4 6M.7 4L3.3 4',Y:'M0 0L2 3L4 0M2 3L2 6',L:'M0 0L0 6L4 6',F:'M4 0L0 0L0 6M0 3L3.2 3',T:'M0 0L4 0M2 0L2 6'}
|
||||||
|
const txt=(c,s,x,y,k,col,w)=>{
|
||||||
|
const a=5.4*k,W=s.length*a-1.4*k;c.beginPath()
|
||||||
|
;[...s].forEach((ch,j)=>{const ox=x-W/2+j*a;for(const[,o,q]of(G[ch]||'').matchAll(/([MLQ])([^MLQ]*)/g)){const n=q.trim().split(/[ ,]+/).map((v,m)=>m%2?y+v*k:ox+v*k);o=='M'?c.moveTo(...n):o=='L'?c.lineTo(...n):c.quadraticCurveTo(...n)}})
|
||||||
|
for(const[l,s]of[[w+6,'#111'],[w,col]])c.lineWidth=l,c.strokeStyle=s,c.stroke();c.strokeStyle='#111'
|
||||||
|
}
|
||||||
|
const LEFT=['1 SEC LEFT','4 MIN LEFT','3 HRS LEFT','9 DAYS LEFT'],BX=34,BW=188,BY=116,BH=46
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const ph=t*4%1,st=sin(PI*min(1,ph/.8))**2,n=i%2?1:-1,sh=st>.5?n:0,fw=BW*(.9+.085*st)
|
||||||
|
c.save();c.translate(sh,0)
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.roundRect(14,46,228,170,18);c.fill();c.stroke()
|
||||||
|
txt(c,'99%',128,60,6,'#fff',6)
|
||||||
|
// track, striped fill with a face at the front pushing
|
||||||
|
c.fillStyle='#e9ecef';c.beginPath();c.roundRect(BX,BY,BW,BH,10);c.fill()
|
||||||
|
c.save();c.beginPath();c.roundRect(BX,BY,fw,BH,10);c.clip();c.fillStyle='#40c057';c.fillRect(BX,BY,fw,BH)
|
||||||
|
c.fillStyle='#69db7c';for(let x=BX-40+(t*4*24)%24;x<BX+fw;x+=24)c.beginPath(),c.moveTo(x,BY+BH),c.lineTo(x+12,BY+BH),c.lineTo(x+30,BY),c.lineTo(x+18,BY),c.fill()
|
||||||
|
c.restore();c.lineWidth=5;c.beginPath();c.roundRect(BX,BY,fw,BH,10);c.stroke()
|
||||||
|
c.lineWidth=7;c.beginPath();c.roundRect(BX,BY,BW,BH,10);c.stroke()
|
||||||
|
const fx=BX+fw-26,fy=BY+BH/2
|
||||||
|
c.lineWidth=4;c.fillStyle='#111'
|
||||||
|
if(st>.4){for(const d of[-1,1])c.beginPath(),c.moveTo(fx+d*13,fy-13),c.lineTo(fx+d*5,fy-8),c.lineTo(fx+d*13,fy-3),c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.roundRect(fx-10,fy+2,20,11,3);c.fill();c.stroke();c.lineWidth=3;c.beginPath();c.moveTo(fx-3,fy+2);c.lineTo(fx-3,fy+13);c.moveTo(fx+4,fy+2);c.lineTo(fx+4,fy+13);c.moveTo(fx-10,fy+7.5);c.lineTo(fx+10,fy+7.5);c.stroke()}
|
||||||
|
else{for(const d of[-1,1])c.beginPath(),c.arc(fx+d*8,fy-5,3.5,0,T),c.fill();c.beginPath();c.arc(fx,fy+11,5,PI*1.15,PI*1.85);c.stroke()}
|
||||||
|
// time left, longer every push
|
||||||
|
txt(c,LEFT[t*4|0],128,180,2.6,'#ffd43b',3.5)
|
||||||
|
c.restore()
|
||||||
|
// sweat flying off
|
||||||
|
if(st>.3){c.fillStyle='#74c0fc';c.lineWidth=4;for(const[x,y,d,z]of[[236,52,1,1.3],[20,60,-1,1]]){const p=st,sx=x+d*p*8,sy=y-p*10;c.save();c.translate(sx,sy);c.rotate(d*.5);c.scale(z,z);c.beginPath();c.moveTo(0,-12);c.quadraticCurveTo(8,0,0,5);c.quadraticCurveTo(-8,0,0,-12);c.fill();c.stroke();c.restore()}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// sunny day except for one guy's personal raincloud; he opens an umbrella, the cloud just shrinks and sneaks under it to keep raining on him
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=36,delay=80,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),lp=(a,b,u)=>a+(b-a)*u
|
||||||
|
const SKY='#d0ebff',GRASS='#8ce99a',SUN='#ffd43b',CLD='#adb5bd',RAIN='#339af0',UMB='#ff6b6b',UMD='#e03131',SKIN='#ffd3b0',HAIR='#5c3d2e',SH='#ffa94d'
|
||||||
|
const UX=150,HX=118,HY=168
|
||||||
|
const cloud=(c,x,y,s,u)=>{
|
||||||
|
const B=[[-26,4,20],[0,-8,26],[26,2,20],[-12,10,16],[14,12,16]]
|
||||||
|
c.save();c.translate(x,y);c.scale(s,s);c.fillStyle='#111';for(const[a,b,r]of B)c.beginPath(),c.arc(a,b,r+5/s,0,T),c.fill()
|
||||||
|
c.fillStyle=CLD;for(const[a,b,r]of B)c.beginPath(),c.arc(a,b,r,0,T),c.fill()
|
||||||
|
c.fillStyle='#ced4da';c.beginPath();c.arc(-4,-16,10,0,T);c.fill()
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*10+6*u,2+4*u,3.5,0,T),c.fill()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=3/s+1;c.beginPath();c.moveTo(-8+6*u,12+4*u);c.quadraticCurveTo(6*u,18+4*u,8+6*u,10+4*u);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const o=io((t-.08)/.06)-io((t-.74)/.06),W=10+82*o
|
||||||
|
let cx,cy,cs,cu=0
|
||||||
|
if(t<.24)cx=128,cy=38,cs=1
|
||||||
|
else if(t<.32){const u=io((t-.24)/.08);cx=lp(128,214,u),cy=lp(38,58,u),cs=1,cu=u}
|
||||||
|
else if(t<.4){const u=io((t-.32)/.08);cx=214,cy=lp(58,120,u),cs=lp(1,.55,u),cu=1}
|
||||||
|
else if(t<.47){const u=io((t-.4)/.07);cx=lp(214,124,u),cy=120,cs=.55,cu=1}
|
||||||
|
else if(t<.8)cx=124,cy=120,cs=.55,cu=1
|
||||||
|
else{const u=io((t-.8)/.16);cx=lp(124,128,u),cy=lp(120,38,u),cs=lp(.55,1,u),cu=1-u}
|
||||||
|
cy+=2*sin(T*t*4)
|
||||||
|
const under=cy>90,moving=t>.24&&t<.47
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=SKY;c.fill();c.clip()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=SUN
|
||||||
|
c.save();c.translate(36,36);for(let k=0;k<8;k++)c.rotate(T/8),c.beginPath(),c.moveTo(30,0),c.lineTo(40,0),c.stroke()
|
||||||
|
c.beginPath();c.arc(0,0,22,0,T);c.fill();c.stroke();c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*8,-3,2.8,0,T),c.fill()
|
||||||
|
c.lineWidth=3.5;c.beginPath();c.arc(0,4,8,.15*PI,.85*PI);c.stroke();c.restore()
|
||||||
|
c.fillStyle=GRASS;c.lineWidth=6;c.beginPath();c.moveTo(0,222);c.quadraticCurveTo(128,212,256,222);c.lineTo(256,256);c.lineTo(0,256);c.fill();c.stroke()
|
||||||
|
for(const[x,col]of[[34,'#f783ac'],[222,'#ffd43b']]){c.lineWidth=4;c.beginPath();c.moveTo(x,232);c.lineTo(x,212);c.stroke();c.fillStyle=col;for(let k=0;k<5;k++)c.beginPath(),c.arc(x+7*cos(k*T/5),206+7*sin(k*T/5),5,0,T),c.fill(),c.stroke();c.fillStyle='#fff';c.beginPath();c.arc(x,206,4,0,T);c.fill();c.stroke()}
|
||||||
|
const wet=!moving
|
||||||
|
c.fillStyle='#74c0fc';c.lineWidth=4;c.beginPath();c.ellipse(HX,230,40+4*sin(T*t*2),7,0,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=6;c.fillStyle=SH;c.beginPath();c.moveTo(HX-28,230);c.lineTo(HX-24,196);c.quadraticCurveTo(HX,186,HX+24,196);c.lineTo(HX+28,230);c.closePath();c.fill();c.stroke()
|
||||||
|
for(const[w,s]of[[18,'#111'],[9,SH]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(HX+20,202),c.lineTo(UX-4,192),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.moveTo(UX,62);c.lineTo(UX,200);c.arc(UX-9,200,9,0,PI*.9);c.stroke()
|
||||||
|
c.fillStyle=SKIN;c.lineWidth=5;c.beginPath();c.arc(UX,192,8,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.translate(HX,HY);c.lineWidth=6;c.fillStyle=SKIN;c.beginPath();c.arc(0,0,30,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HAIR;c.beginPath();c.moveTo(-30,0);c.quadraticCurveTo(-32,-32,0,-31);c.quadraticCurveTo(32,-32,30,0);c.lineTo(24,-10);c.lineTo(17,-1);c.lineTo(9,-12);c.lineTo(0,-2);c.lineTo(-9,-12);c.lineTo(-17,-1);c.lineTo(-24,-10);c.closePath();c.fill();c.stroke()
|
||||||
|
const up=under&&t<.8?1:0
|
||||||
|
c.fillStyle='#111';c.lineWidth=4
|
||||||
|
for(const d of[-1,1]){c.beginPath();c.arc(d*11,11-3*up,4,0,T);c.fill();c.beginPath();c.moveTo(d*11-7,6-3*up);c.lineTo(d*11+7,6-3*up);c.stroke()}
|
||||||
|
c.beginPath();c.moveTo(-6,24);c.lineTo(6,23);c.stroke()
|
||||||
|
if(wet){c.fillStyle=RAIN;c.lineWidth=3;for(const[x,o]of[[-30,0],[28,.4],[-20,.7]]){const p=(t*3+o)%1,y=4+p*18;c.beginPath();c.moveTo(x,y-6);c.quadraticCurveTo(x+5,y+2,x,y+5);c.quadraticCurveTo(x-5,y+2,x,y-6);c.fill();c.stroke()}}
|
||||||
|
c.restore()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=UMB
|
||||||
|
c.beginPath();c.moveTo(UX-W,104);c.bezierCurveTo(UX-W,76,UX-W*.5,64,UX,62);c.bezierCurveTo(UX+W*.5,64,UX+W,76,UX+W,104)
|
||||||
|
for(let k=3;k>=0;k--){const a=UX-W+W*k/2,b=a+W/2;c.quadraticCurveTo((a+b)/2,96,a,104)}
|
||||||
|
c.closePath();c.fill();c.stroke()
|
||||||
|
if(W>30){c.strokeStyle=UMD;c.lineWidth=5;c.beginPath();for(const d of[-.5,.5])c.moveTo(UX+d*W*.2,66),c.quadraticCurveTo(UX+d*W*.75,72,UX+d*W*.98,100);c.stroke()}
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.moveTo(UX,62);c.lineTo(UX,54);c.stroke()
|
||||||
|
c.strokeStyle=RAIN;c.lineWidth=4
|
||||||
|
for(let k=0;k<7;k++){
|
||||||
|
const x=cx+(k-3)*12*cs,p=((t*4+k*.37)%1),y0=cy+18*cs,hit=!under&&o>.4&&abs(x-UX)<W?72+28*((x-UX)/W)**2:abs(x-HX)<30?HY-30+((x-HX)/30)**2*24:220,y=y0+(hit-y0)*p
|
||||||
|
if(hit<=y0||moving&&k%2)continue
|
||||||
|
c.beginPath();c.moveTo(x,y);c.lineTo(x-2,y+10*cs);c.stroke()
|
||||||
|
if(p>.75){c.lineWidth=3;c.beginPath();c.moveTo(x-6,hit-2);c.lineTo(x-10,hit-8);c.moveTo(x+6,hit-2);c.lineTo(x+10,hit-8);c.stroke();c.lineWidth=4}
|
||||||
|
}
|
||||||
|
cloud(c,cx,cy,cs,cu)
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// fist holds up a receipt that drops and keeps unrolling until it heaps up in folds on the floor, gets a smug shake, then zips back up
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
export const frames=32,delay=[...Array(31).fill(70),600],rim=4
|
||||||
|
const SK='#ffd8b5',SL='#5c7cfa',PA='#fff',LN='#868e96',W=84,X=128-W/2,TOP=70,FLR=238
|
||||||
|
const ease=x=>x<=0?0:x>=1?1:x*x
|
||||||
|
const lines=(c,y1,x)=>{for(let k=0;k*14+TOP+14<y1-4;k++){const y=TOP+14+k*14,m=k%6;c.lineWidth=4;c.strokeStyle=m==4?'#111':LN;c.beginPath();if(m==4){c.moveTo(x+8,y);c.lineTo(x+W-8,y)}else{c.moveTo(x+9,y);c.lineTo(x+20+(k*17)%26,y);c.moveTo(x+W-24+(k%3)*4,y);c.lineTo(x+W-9,y)}c.stroke()}c.strokeStyle='#111'}
|
||||||
|
const FOLD=[[-14,.05],[16,-.06],[-6,.08],[22,-.04],[-20,-.07],[8,.06]]
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const dn=ease((t-.04)/.34),up=t>.84?min(1,(t-.84)/.1):0,L=(1-up)*dn*300,n=min(6,max(0,(L-(FLR-TOP-24))/16|0))
|
||||||
|
const sh=t>.46&&t<.8?7*sin(T*(t-.46)*6):0
|
||||||
|
c.save();c.translate(sh,0)
|
||||||
|
// heap of curls on the floor, each one a loop of paper ribbon
|
||||||
|
for(let k=0;k<n;k++){const[o,a]=FOLD[k],y=FLR-14-k*9;c.save();c.translate(128+o*1.6-sh*.6,y);c.rotate(a*2)
|
||||||
|
for(const[w,s]of[[24,'#111'],[16,PA]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.ellipse(0,0,34+(k%3)*6,12,0,0,T),c.stroke()
|
||||||
|
c.lineWidth=3;c.strokeStyle=LN;c.setLineDash([8,7]);c.beginPath();c.ellipse(0,0,34+(k%3)*6,12,0,0,T);c.stroke();c.setLineDash([]);c.strokeStyle='#111';c.restore()}
|
||||||
|
// hanging strip, sways a little behind the shake
|
||||||
|
const b=n?FLR-14-(n-1)*9:TOP+min(L,FLR-TOP-10),x=X-sh*.6
|
||||||
|
if(L>2){c.fillStyle=PA;c.lineWidth=7;c.beginPath();c.moveTo(X,TOP);c.lineTo(X+W,TOP);c.lineTo(x+W,b)
|
||||||
|
if(!n)for(let k=1;k<=8;k++)c.lineTo(x+W-k*W/8,b+(k%2?7:0));else c.lineTo(x,b)
|
||||||
|
c.closePath();c.fill();c.stroke();c.save();c.clip();lines(c,b,X);c.restore()}
|
||||||
|
// sleeve and fist
|
||||||
|
c.fillStyle=SL;c.lineWidth=7;c.beginPath();c.roundRect(84,-14,88,42,8);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SK;c.beginPath();c.roundRect(72,22,112,58,24);c.fill();c.stroke()
|
||||||
|
c.lineWidth=6;for(const x of[100,128,156])c.beginPath(),c.moveTo(x,27),c.lineTo(x,56),c.stroke()
|
||||||
|
c.lineWidth=7;c.beginPath();c.roundRect(64,50,78,28,14);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(126,58);c.lineTo(130,70);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// smug shake marks
|
||||||
|
if(sh){c.lineWidth=6;for(const d of[-1,1])for(const[y,s]of[[30,-1],[60,1]])c.beginPath(),c.moveTo(128+d*(70+(i%2)*4),y),c.lineTo(128+d*(88+(i%2)*4),y+s*6),c.stroke()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// heart-eyed little guy happily hops and waves red flags while more and more red flags spring up all around him
|
||||||
|
const{sin,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=12,delay=Array(12).fill(100),rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u*u*(3-2*u)),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||||
|
const K='#1b1b1f',R='#fa5252',C='#fff3bf'
|
||||||
|
const flag=(c,x,y,h,d,ph,a=0,W=40,H=27)=>{c.save();c.translate(x,y);c.rotate(a)
|
||||||
|
for(const[w,s]of[[10,K],[4,'#e9ecef']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(0,0),c.lineTo(0,-h),c.stroke()
|
||||||
|
const o=k=>4*sin(ph-k*2.6)*k;c.strokeStyle=K;c.lineWidth=5;c.fillStyle=R;c.beginPath()
|
||||||
|
for(let k=0;k<=1;k+=.25)c.lineTo(d*W*k,-h+o(k))
|
||||||
|
for(let k=1;k>=0;k-=.25)c.lineTo(d*W*k,-h+H+o(k))
|
||||||
|
c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#ffd43b';c.lineWidth=4;c.beginPath();c.arc(0,-h-3,5,0,T);c.fill();c.stroke();c.restore()}
|
||||||
|
const heart=(c,x,y,s)=>{c.save();c.translate(x,y);c.scale(s,s);c.beginPath();c.moveTo(0,8);c.bezierCurveTo(-16,-2,-10,-16,0,-7);c.bezierCurveTo(10,-16,16,-2,0,8);c.fillStyle='#f06595';c.fill();c.lineWidth=3;c.stroke();c.restore()}
|
||||||
|
export default(c,t)=>{
|
||||||
|
const ph=T*t*2,sink=io((t-.84)/.12)
|
||||||
|
// ground flags pop up one after another, then all sink back at the end of the loop
|
||||||
|
for(const[x,y,h,d,t0]of[[22,214,84,1,.06],[234,214,84,-1,.2],[44,250,52,1,.34],[212,250,52,-1,.48]]){const s=bk((t-t0)/.1)*(1-sink);if(s>.02){c.save();c.translate(x,y);c.scale(1,s);flag(c,0,0,h,d,ph+x,0,34,23);c.restore()}}
|
||||||
|
const hop=abs(sin(ph)),sq=1-.07*(1-hop)
|
||||||
|
c.save();c.translate(128,240);c.scale(2-sq,sq);c.translate(-128,-240-10*hop)
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.fillStyle='#ffe066'
|
||||||
|
for(const x of[112,144])c.beginPath(),c.ellipse(x,230,14,9,0,0,T),c.fill(),c.stroke()
|
||||||
|
// arms wave the flags alternately
|
||||||
|
const w=sin(ph),ax=[[94,176,84,124-10*w,-.32+.22*w,-1],[162,176,172,124+10*w,.32+.22*w,1]]
|
||||||
|
for(const[sx,sy,hx,hy,a,d]of ax)flag(c,hx,hy+8,72,d,ph+sx,a)
|
||||||
|
for(const[sx,sy,hx,hy]of ax){for(const[lw,s]of[[20,K],[9,C]])c.lineWidth=lw,c.strokeStyle=s,c.beginPath(),c.moveTo(sx,sy),c.lineTo(hx,hy),c.stroke()
|
||||||
|
c.strokeStyle=K;c.fillStyle=C;c.lineWidth=5;c.beginPath();c.arc(hx,hy,10,0,T);c.fill();c.stroke()}
|
||||||
|
c.fillStyle=C;c.lineWidth=6;c.beginPath();c.ellipse(128,184,44,46,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.ellipse(108,156,8,12,.6,0,T);c.fill()
|
||||||
|
const hs=1.1+.18*abs(sin(ph*2));heart(c,110,176,hs);heart(c,146,176,hs)
|
||||||
|
c.fillStyle=K;c.beginPath();c.moveTo(116,194);c.quadraticCurveTo(128,192,140,194);c.quadraticCurveTo(138,212,128,212);c.quadraticCurveTo(118,212,116,194);c.fill()
|
||||||
|
c.fillStyle='#ff8787';c.beginPath();c.ellipse(128,207,6,3.5,0,0,T);c.fill()
|
||||||
|
c.fillStyle='#ffa8a8';for(const x of[96,160])c.beginPath(),c.ellipse(x,196,7,4.5,0,0,T),c.fill()
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
// a long heartfelt blue text message, then the typing dots go on and off forever... and the reply is just "k"
|
||||||
|
const{sin,PI,min,max}=Math,T=2*PI
|
||||||
|
export const frames=36,delay=[...Array(35).fill(90),1600],rim=4
|
||||||
|
const BL='#339af0',GR='#e9ecef'
|
||||||
|
const ease=x=>x<=0?0:x>=1?1:1+sin(PI*x)*.4*(1-x)
|
||||||
|
const bub=(c,x,y,w,h,col,d)=>{
|
||||||
|
c.fillStyle=col;c.lineWidth=6;const tx=d>0?x+w-18:x+18
|
||||||
|
c.beginPath();c.moveTo(tx-10*d,y+h-12);c.quadraticCurveTo(tx+12*d,y+h+6,tx+20*d,y+h+10);c.quadraticCurveTo(tx+8*d,y+h-2,tx+8*d,y+h-14);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(x,y,w,h,20);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.moveTo(tx-6*d,y+h-14);c.quadraticCurveTo(tx+10*d,y+h+2,tx+14*d,y+h+5);c.quadraticCurveTo(tx+6*d,y+h-4,tx+6*d,y+h-16);c.fill()
|
||||||
|
}
|
||||||
|
export default(c,t)=>{
|
||||||
|
// the long message
|
||||||
|
bub(c,58,14,184,120,BL,1)
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=8;for(const[k,l]of[[0,150],[1,140],[2,156],[3,128],[4,72]].entries())c.beginPath(),c.moveTo(76,34+k*20),c.lineTo(76+l[1]-12,34+k*20),c.stroke()
|
||||||
|
c.fillStyle='#ff6b6b';c.strokeStyle='#111';c.lineWidth=3.5;c.save();c.translate(150,114);c.beginPath();c.moveTo(0,7);c.bezierCurveTo(-12,-1,-8,-11,0,-4);c.bezierCurveTo(8,-11,12,-1,0,7);c.fill();c.stroke();c.restore()
|
||||||
|
// tiny "read" double tick under it
|
||||||
|
c.strokeStyle='#4dabf7';c.lineWidth=3.5;for(const o of[0,7])c.beginPath(),c.moveTo(214+o,154),c.lineTo(219+o,159),c.lineTo(228+o,148),c.stroke()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
// typing... stop... typing... k
|
||||||
|
const on=(t>.03&&t<.36)||(t>.47&&t<.75),K=t>=.8
|
||||||
|
if(on){const s=t<.36?ease((t-.03)/.05):ease((t-.47)/.05);c.save();c.translate(24,208);c.scale(s,s);c.translate(-24,-208)
|
||||||
|
bub(c,14,170,96,50,GR,-1)
|
||||||
|
for(let k=0;k<3;k++){const b=max(0,sin(T*(t*6-k*.18)));c.fillStyle=b>.3?'#495057':'#adb5bd';c.beginPath();c.arc(40+k*22,195-b*6,7,0,T);c.fill()}
|
||||||
|
c.restore()}
|
||||||
|
if(K){const s=ease((t-.8)/.06);c.save();c.translate(24,220);c.scale(s,s);c.translate(-24,-220)
|
||||||
|
bub(c,14,166,58,56,GR,-1)
|
||||||
|
c.lineWidth=7;c.beginPath();c.moveTo(34,178);c.lineTo(34,210);c.moveTo(52,188);c.lineTo(35,200);c.moveTo(41,196);c.lineTo(53,210);c.stroke()
|
||||||
|
c.restore()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// round-bottomed blob laughing so hard it keeps rolling over backwards, feet kicking in the air, tears spraying, HA HA popping out
|
||||||
|
const{sin,cos,PI,max,min,abs}=Math,T=2*PI
|
||||||
|
export const frames=12,delay=90,rim=5
|
||||||
|
const Y='#ffd43b',BL='#ff8787',MO='#c92a2a',TG='#ff8fab',TR='#74c0fc',HC=['#ff6b6b','#4dabf7','#51cf66']
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const G={H:[[0,0,0,6],[4,0,4,6],[0,3,4,3]],A:[[0,6,2,0,4,6],[.9,3.8,3.1,3.8]]}
|
||||||
|
const word=(c,s,h,col)=>{
|
||||||
|
const k=h/6,W=(s.length*6-2)*k
|
||||||
|
for(const[w,st]of[[h*.5,'#111'],[h*.25,col]]){c.lineWidth=w;c.strokeStyle=st;let x=-W/2;c.beginPath()
|
||||||
|
for(const ch of s){for(const p of G[ch]){c.moveTo(x+p[0]*k,p[1]*k-h/2);for(let q=2;q<p.length;q+=2)c.lineTo(x+p[q]*k,p[q+1]*k-h/2)}x+=6*k}
|
||||||
|
c.stroke()}
|
||||||
|
c.strokeStyle='#111'}
|
||||||
|
export default(c,t)=>{
|
||||||
|
c.save();c.translate(128,240);c.scale(.9,.9);c.translate(-128,-240)
|
||||||
|
const rb=62,th=.1-.72*(.5-.5*cos(t*T)),X=146+rb*th,F=236,sh=abs(sin(t*T*3)),back=-th/.62
|
||||||
|
// floor
|
||||||
|
c.lineWidth=8;c.beginPath();c.moveTo(14,F+4);c.lineTo(242,F+4);c.stroke()
|
||||||
|
c.save();c.translate(X,F-rb);c.rotate(th);c.translate(0,rb)
|
||||||
|
// feet kicking more the further it tips back
|
||||||
|
for(const d of[-1,1]){const k=sin(t*T*4+(d>0?PI:0))*max(0,back);c.save();c.translate(d*26,-14);c.rotate(d*.3+k*.7);c.fillStyle=Y;c.lineWidth=6;c.beginPath();c.roundRect(-12,-4,24,30,12);c.fill();c.stroke();c.restore()}
|
||||||
|
// body
|
||||||
|
c.lineWidth=7;c.fillStyle=Y;c.beginPath();c.moveTo(0,0);c.arc(0,-rb,rb,PI/2,PI);c.bezierCurveTo(-rb,-130,-40,-164,0,-164);c.bezierCurveTo(40,-164,rb,-130,rb,-rb);c.arc(0,-rb,rb,0,PI/2);c.closePath();c.fill();c.stroke()
|
||||||
|
// eyes squeezed shut
|
||||||
|
c.lineWidth=6;for(const d of[-1,1])c.beginPath(),c.moveTo(d*10,-120),c.lineTo(d*27,-112),c.lineTo(d*10,-104),c.stroke()
|
||||||
|
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(d*40,-92,10,6,0,0,T),c.fill()
|
||||||
|
// laughing mouth
|
||||||
|
const mh=20+7*sh,M=()=>{c.beginPath();c.moveTo(-24,-96);c.lineTo(24,-96);c.quadraticCurveTo(24,-86+mh,0,-86+mh);c.quadraticCurveTo(-24,-86+mh,-24,-96);c.closePath()}
|
||||||
|
c.fillStyle=MO;M();c.fill();c.save();c.clip();c.fillStyle=TG;c.beginPath();c.ellipse(0,-86+mh,15,9,0,0,T);c.fill();c.fillStyle='#fff';c.fillRect(-22,-96,44,6);c.restore()
|
||||||
|
c.lineWidth=5.5;M();c.stroke()
|
||||||
|
// hands clutching the belly
|
||||||
|
for(const d of[-1,1]){const hx=d*(20+3*sh);for(const[w,st]of[[22,'#111'],[9,Y]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(d*58,-78),c.quadraticCurveTo(d*56,-44,hx+d*8,-40),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.fillStyle=Y;c.lineWidth=6;c.beginPath();c.ellipse(hx,-40,13,11,d*.4,0,T);c.fill();c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
// tears spraying off both eyes
|
||||||
|
for(let k=0;k<6;k++){const q=(t*2+k/6)%1,d=k%2?1:-1,lx=d*30,ly=-112+rb,ex=X+cos(th)*lx-sin(th)*(ly),ey=F-rb+sin(th)*lx+cos(th)*ly
|
||||||
|
const x=ex+d*(8+q*44),y=ey-40*q+80*q*q,s=1-q*.5;if(q<.85){c.fillStyle=TR;c.lineWidth=3.5;c.beginPath();c.ellipse(x,y,5.5*s,7.5*s,d*.5,0,T);c.fill();c.stroke()}}
|
||||||
|
c.restore()
|
||||||
|
// HA popping around, each one holds still once it's out
|
||||||
|
const S=[[52,52,-.25],[204,44,.22],[212,126,.3]]
|
||||||
|
for(let k=0;k<3;k++){const q=(t*2+k/3)%1;if(q<.62){const[x,y,r]=S[k],s=q<.1?1.25:1;c.save();c.translate(x,y);c.rotate(r);c.scale(s,s);word(c,'HA',32,HC[k]);c.restore()}}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
// a grumpy salt shaker with folded arms glares sideways, then furiously shakes itself, spraying salt everywhere, and huffs: SALTY
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=30,delay=80,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)}
|
||||||
|
const G={S:'82602002042666888a6c2c0a',A:'0c0440848c 0787',L:'000c8c',T:'0080 404c',Y:'004680 464c'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const BX=128,BY=204,S0=.3,S1=.62,rot=t=>t>S0&&t<S1?.42*sin((t-S0)/(S1-S0)*T*3):0,hop=t=>t>S0&&t<S1?12*abs(sin((t-S0)/(S1-S0)*PI*3)):0
|
||||||
|
const rnd=k=>{const x=sin(k*127.1+311.7)*43758.5453;return x-Math.floor(x)}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const r=rot(t),h=hop(t),mad=t>S0-.04&&t<S1+.2,look=t<S0?(t<.15?-1:1):t>.85?-1:0
|
||||||
|
// salt grains thrown out of the cap: each launched at its own moment with the cap's tilt at that time
|
||||||
|
c.lineWidth=2;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||||
|
for(let k=0;k<110;k++){const te=S0+(S1-S0)*k/110,u=t-te;if(u<0||u>.12)continue
|
||||||
|
const rr=rot(te);if(abs(rr)<.12)continue
|
||||||
|
const a=-PI/2+rr*3+(rnd(k)-.5)*.8,sp=260+260*rnd(k+9),cx=BX+sin(rr)*150,cy=BY-hop(te)-cos(rr)*150
|
||||||
|
const x=cx+cos(a)*sp*u,y=cy+sin(a)*sp*u+3000*u*u,z=2.5+1.5*rnd(k+3)
|
||||||
|
c.beginPath();c.rect(x-z,y-z,2*z,2*z);c.fill();c.stroke()}
|
||||||
|
c.save();c.translate(BX,BY-h);c.rotate(r)
|
||||||
|
// feet
|
||||||
|
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(d*24,2,13,7,0,0,T),c.fill()
|
||||||
|
// glass body with salt inside
|
||||||
|
const body=()=>{c.beginPath();c.moveTo(-50,-4);c.lineTo(-42,-118);c.lineTo(42,-118);c.lineTo(50,-4);c.quadraticCurveTo(50,4,40,4);c.lineTo(-40,4);c.quadraticCurveTo(-50,4,-50,-4);c.closePath()}
|
||||||
|
c.fillStyle='#e7f5ff';body();c.fill()
|
||||||
|
c.save();body();c.clip();c.fillStyle='#fff';c.beginPath();c.moveTo(-60,-52+r*30);c.quadraticCurveTo(0,-60,60,-52-r*30);c.lineTo(60,10);c.lineTo(-60,10);c.fill()
|
||||||
|
c.fillStyle='#ced4da';for(let k=0;k<14;k++)c.beginPath(),c.arc(-38+76*rnd(k+40),-40+40*rnd(k+70),2,0,T),c.fill()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=6;c.beginPath();c.moveTo(-30,-108);c.lineTo(-34,-64);c.stroke();c.restore()
|
||||||
|
c.lineWidth=7;c.strokeStyle='#111';body();c.stroke()
|
||||||
|
// cap
|
||||||
|
c.fillStyle='#ced4da';c.lineWidth=6;c.beginPath();c.roundRect(-46,-132,92,18,6);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.moveTo(-40,-132);c.bezierCurveTo(-38,-162,38,-162,40,-132);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';for(const[x,y]of[[-16,-142],[0,-146],[16,-142],[-8,-152],[8,-152]])c.beginPath(),c.arc(x,y,2.6,0,T),c.fill()
|
||||||
|
c.strokeStyle='#868e96';c.lineWidth=3;for(let x=-36;x<=36;x+=12)c.beginPath(),c.moveTo(x,-129),c.lineTo(x,-117),c.stroke()
|
||||||
|
// grumpy face
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
for(const d of[-1,1]){const x=d*18,y=-90
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.ellipse(x,y,11,10,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.arc(x+look*5,y+2,4.5,0,T);c.fill()
|
||||||
|
c.fillStyle='#e7f5ff';c.beginPath();c.moveTo(x-13,y-12);c.lineTo(x+13,y-12);c.lineTo(x+13,y-2+d*(mad?3:1));c.lineTo(x-13,y-2-d*(mad?3:1));c.closePath();c.fill()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(x-11,y-2-d*(mad?3:1)*.85);c.lineTo(x+11,y-2+d*(mad?3:1)*.85);c.stroke()
|
||||||
|
c.lineWidth=6;c.beginPath();c.moveTo(d*6,y-12);c.lineTo(d*30,y-20-(mad?2:0));c.stroke()}
|
||||||
|
c.lineWidth=4.5;c.beginPath();if(mad){c.moveTo(-12,-64);c.lineTo(-6,-69);c.lineTo(0,-64);c.lineTo(6,-69);c.lineTo(12,-64)}else{c.moveTo(-10,-64);c.quadraticCurveTo(0,-71,10,-64)}c.stroke()
|
||||||
|
// folded arms, each hand tucked under the other elbow
|
||||||
|
const arm=(d,full)=>{for(const[w,s]of[[16,'#111'],[8,'#e7f5ff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.moveTo(d*44,-66);c.quadraticCurveTo(d*54,-50,d*46,-36);if(full)c.quadraticCurveTo(0,-30,-d*34,-42+d*2);c.stroke()}}
|
||||||
|
arm(-1,1);arm(1,1);arm(-1,0)
|
||||||
|
// anger mark on the cap while shaking
|
||||||
|
if(mad){c.strokeStyle='#e03131';c.lineWidth=4;const s=1+.15*(i%2);c.save();c.translate(34,-150);c.scale(s,s);for(let k=0;k<4;k++){c.rotate(PI/2);c.beginPath();c.moveTo(3,-9);c.quadraticCurveTo(3,-3,9,-3);c.stroke()}c.restore()}
|
||||||
|
c.restore()
|
||||||
|
// huff puffs after the tantrum
|
||||||
|
const hf=ez(t,.64,.76)*(1-ez(t,.8,.88));if(hf>0)for(const d of[-1,1]){const x=BX+d*(52+34*hf),y=70-14*hf,s=.4+.8*hf
|
||||||
|
c.save();c.translate(x,y);c.scale(d*s,s);c.fillStyle='#fff';c.strokeStyle='#111';c.lineWidth=4/s;c.beginPath();c.arc(0,0,10,PI*.5,PI*1.5);c.arc(10,-8,9,PI*1.1,PI*1.9);c.arc(22,-2,10,PI*1.4,PI*.6);c.closePath();c.fill();c.stroke();c.restore()}
|
||||||
|
txt(c,'SALTY',BX,236,22,'#fff')
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
// midnight kitchen: a guy in pajamas opens the fridge, stares at the same lone pickle, closes it, glances at you, and opens it again just in case
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=32,delay=85,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),bump=(t,m,w)=>io(1-abs(((t-m+1.5)%1)-.5)/w)
|
||||||
|
const WALL='#b197fc',FL='#9775fa',FR='#f1f3f5',IN='#fff9db',SH='#a5d8ff',PJ='#ffc9c9',PS='#fa5252',SKIN='#ffd3b0',HAIR='#5c3d2e',PK='#82c91e',JAR='#e3fafc'
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const op=io((t-.06)/.1)-io((t-.54)/.1),w=106*cos(op*1.42),fx=236-w,sp=10*sin(op*1.42),look=bump(t,.75,.14),rch=max(bump(t,.04,.1),bump(t,.55,.1)),bl=i==14||i==26
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=WALL;c.fill();c.clip()
|
||||||
|
c.fillStyle=FL;c.fillRect(0,222,256,40);c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.moveTo(0,222);c.lineTo(256,222);c.stroke()
|
||||||
|
c.lineWidth=5;c.fillStyle='#fff';c.beginPath();c.arc(36,38,16,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.beginPath();c.moveTo(36,38);c.lineTo(36,28);c.moveTo(36,38);c.lineTo(44,38);c.stroke()
|
||||||
|
c.lineWidth=6;c.fillStyle=FR;c.beginPath();c.roundRect(130,26,106,212,10);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.moveTo(130,92);c.lineTo(236,92);c.stroke()
|
||||||
|
c.lineWidth=7;c.beginPath();c.moveTo(142,48);c.lineTo(142,76);c.stroke()
|
||||||
|
for(const[x,y,col]of[[180,44,'#ff6b6b'],[208,62,'#ffd43b'],[196,40,'#4dabf7']])c.fillStyle=col,c.lineWidth=4,c.beginPath(),c.arc(x,y,6,0,T),c.fill(),c.stroke()
|
||||||
|
c.save();c.translate(170,62);c.rotate(-.08);c.fillStyle='#fff';c.lineWidth=3;c.beginPath();c.rect(-12,-12,24,22);c.fill();c.stroke();c.strokeStyle='#40c057';c.beginPath();c.moveTo(-6,6);c.lineTo(-2,-4);c.lineTo(3,4);c.lineTo(7,-2);c.stroke();c.restore()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
if(op>.01){
|
||||||
|
c.fillStyle=IN;c.lineWidth=5;c.beginPath();c.rect(136,98,96,134);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.arc(184,106,7,0,PI);c.fill();c.stroke()
|
||||||
|
c.strokeStyle=SH;c.lineWidth=5;c.beginPath();for(const y of[140,192])c.moveTo(138,y),c.lineTo(230,y);c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=4;c.fillStyle=JAR;c.beginPath();c.roundRect(170,152,36,38,6);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#e03131';c.beginPath();c.roundRect(167,146,42,10,3);c.fill();c.stroke()
|
||||||
|
c.save();c.translate(188,172);c.rotate(.3+.1*sin(T*t*2));c.fillStyle=PK;c.lineWidth=3;c.beginPath();c.ellipse(0,0,8,14,0,0,T);c.fill();c.stroke();c.fillStyle='#5c940d';for(const[a,b]of[[-3,-6],[3,1],[-1,7]])c.beginPath(),c.arc(a,b,1.3,0,T),c.fill();c.restore()
|
||||||
|
}
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=FR
|
||||||
|
c.beginPath();c.moveTo(236,94);c.lineTo(fx,94-sp);c.lineTo(fx,236+sp);c.lineTo(236,236);c.closePath();c.fill();c.stroke()
|
||||||
|
if(w>30){c.lineWidth=7;c.beginPath();c.moveTo(fx+12,110);c.lineTo(fx+12,150);c.stroke()}
|
||||||
|
const hy=4*sin(T*t*2),sx=92,sy=144
|
||||||
|
c.lineWidth=6;c.fillStyle=PJ
|
||||||
|
c.beginPath();c.moveTo(48,226);c.lineTo(48,150);c.quadraticCurveTo(48,132,70,132);c.quadraticCurveTo(94,132,94,150);c.lineTo(94,226);c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle=PS;c.lineWidth=4;c.beginPath();for(const x of[60,72,84])c.moveTo(x,140),c.lineTo(x,222);c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.moveTo(70,184);c.lineTo(70,226);c.stroke()
|
||||||
|
c.fillStyle='#ff8787';for(const x of[56,84])c.beginPath(),c.ellipse(x,228,15,7,0,0,T),c.fill(),c.stroke()
|
||||||
|
const hx=sx+40*rch,hhy=196-44*rch
|
||||||
|
for(const[lw,s]of[[20,'#111'],[10,PJ]])c.lineWidth=lw,c.strokeStyle=s,c.beginPath(),c.moveTo(sx-6,sy),c.quadraticCurveTo(sx+4+10*rch,sy+30-20*rch,hx,hhy),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=SKIN;c.beginPath();c.arc(hx,hhy,8,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.translate(72+7*op,98+hy*.5+3*op);c.rotate(.12*op);c.lineWidth=6
|
||||||
|
c.fillStyle=SKIN;c.beginPath();c.arc(0,0,34,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HAIR;c.beginPath();c.moveTo(-34,-2);c.lineTo(-40,-20);c.lineTo(-26,-22);c.lineTo(-30,-40);c.lineTo(-12,-32);c.lineTo(-6,-46);c.lineTo(8,-34);c.lineTo(22,-44);c.lineTo(24,-28);c.lineTo(40,-26);c.lineTo(32,-10);c.quadraticCurveTo(10,-24,-10,-16);c.quadraticCurveTo(-24,-10,-34,-2);c.closePath();c.fill();c.stroke()
|
||||||
|
const ex=10-10*look,ey=2+3*look
|
||||||
|
c.fillStyle='#111';if(bl){c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.moveTo(ex+d*12-5,ey),c.lineTo(ex+d*12+5,ey),c.stroke()}else for(const d of[-1,1])c.beginPath(),c.arc(ex+d*12,ey,4.5,0,T),c.fill()
|
||||||
|
c.lineWidth=4;c.beginPath();for(const d of[-1,1])c.moveTo(ex+d*12-6,ey-8),c.lineTo(ex+d*12+6,ey-8);c.stroke()
|
||||||
|
c.beginPath();c.moveTo(ex-5,ey+18);c.lineTo(ex+5,ey+18);c.stroke()
|
||||||
|
c.fillStyle='#ff8fa3';c.beginPath();c.ellipse(ex+24,ey+12,6,4,0,0,T);c.fill()
|
||||||
|
c.restore()
|
||||||
|
const L=op,lit=()=>{c.moveTo(232,98);c.lineTo(136,98);c.lineTo(136-136*L,40-30*L);c.lineTo(136-150*L,256);c.lineTo(232,256);c.closePath()}
|
||||||
|
c.fillStyle='rgba(20,18,64,.62)';c.beginPath();c.rect(0,0,256,256);if(L>.01)lit();c.fill('evenodd')
|
||||||
|
if(L>.01&&L<.99){c.fillStyle=`rgba(20,18,64,${(.62*(1-L)).toFixed(2)})`;c.beginPath();lit();c.fill()}
|
||||||
|
if(op>.5){c.fillStyle='#fff';c.strokeStyle='#111';c.lineWidth=4;for(let k=0;k<3;k++)if(t>.22+k*.07&&t<.54)c.beginPath(),c.arc(66+k*15,28,5,0,T),c.fill(),c.stroke()}
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
// social battery with a face draining from green to dead red as "hi!" "hey!" bubbles keep popping up, then it plugs in alone and recharges
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
export const frames=32,delay=[...Array(31).fill(85),500],rim=4
|
||||||
|
const G={S:'M3.8 .9Q3.1 0 2 0Q.2 0 .2 1.5Q.2 2.8 2 3Q3.9 3.2 3.9 4.5Q3.9 6 2 6Q.7 6 0 5.1',O:'M2 0Q0 0 0 3Q0 6 2 6Q4 6 4 3Q4 0 2 0',C:'M4 .9Q3.3 0 2.1 0Q0 0 0 3Q0 6 2.1 6Q3.3 6 4 5.1',I:'M2 0L2 6M.8 0L3.2 0M.8 6L3.2 6',A:'M0 6L2 0L4 6M.7 4L3.3 4',L:'M0 0L0 6L4 6',B:'M0 3L0 0L2.3 0Q3.7 0 3.7 1.5Q3.7 3 2.3 3L0 3L0 6L2.5 6Q4 6 4 4.5Q4 3 2.3 3',T:'M0 0L4 0M2 0L2 6',E:'M4 0L0 0L0 6L4 6M0 3L3.2 3',R:'M0 6L0 0L2.3 0Q4 0 4 1.7Q4 3.4 2.3 3.4L0 3.4M2 3.4L4 6',Y:'M0 0L2 3L4 0M2 3L2 6',H:'M0 0L0 6M4 0L4 6M0 3L4 3','!':'M2 0L2 3.8M2 5.9L2 6','?':'M.1 1.2Q.6 0 2 0Q4 0 4 1.7Q4 3 2 3.3L2 4M2 5.9L2 6',U:'M0 0L0 4Q0 6 2 6Q4 6 4 4L4 0',N:'M0 6L0 0L4 6L4 0',W:'M0 0L.9 6L2 2.4L3.1 6L4 0'}
|
||||||
|
const txt=(c,s,x,y,k,col,w)=>{
|
||||||
|
const a=5.4*k,W=s.length*a-1.4*k;c.beginPath()
|
||||||
|
;[...s].forEach((ch,j)=>{const ox=x-W/2+j*a;for(const[,o,q]of(G[ch]||'').matchAll(/([MLQ])([^MLQ]*)/g)){const n=q.trim().split(/[ ,]+/).map((v,m)=>m%2?y+v*k:ox+v*k);o=='M'?c.moveTo(...n):o=='L'?c.lineTo(...n):c.quadraticCurveTo(...n)}})
|
||||||
|
for(const[l,s]of col?[[w+6,'#111'],[w,col]]:[[w,'#111']])c.lineWidth=l,c.strokeStyle=s,c.stroke();c.strokeStyle='#111'
|
||||||
|
}
|
||||||
|
const BUB=[['HI!',.04,50,62,1],['HEY!',.16,206,78,-1],['HOW R U?',.28,60,172,1],['LUNCH?',.40,204,186,-1]]
|
||||||
|
const ease=x=>x<0?0:x>1?1:1-(1-x)**3,pop=x=>x<=0?0:x>=1?1:1+sin(PI*x)*.35*(1-x)
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const hits=BUB.reduce((s,b)=>s+ease((t-b[1])/.05),0),chg=ease((t-.72)/.22),L=t<.7?max(.05,1-hits*.24):.05+.95*chg,dead=t>.46&&t<.72,sq=dead?.94:1
|
||||||
|
txt(c,'SOCIAL BATTERY',128,8,2.3,'#fff',3.5)
|
||||||
|
// the plug sneaking in to recharge
|
||||||
|
const pl=ease((t-.62)/.08)*(t<.97?1:1-ease((t-.97)/.03))
|
||||||
|
if(pl>0){const px=176+(1-pl)*90;c.lineWidth=7;c.strokeStyle='#111';c.beginPath();c.moveTo(px+20,198);c.bezierCurveTo(px+60,198,px+40,236,262,236);c.stroke();c.lineWidth=3;c.strokeStyle='#868e96';c.stroke();c.strokeStyle='#111'
|
||||||
|
c.fillStyle='#495057';c.lineWidth=6;c.beginPath();c.roundRect(px,186,26,24,5);c.fill();c.stroke()}
|
||||||
|
c.save();c.translate(128,214);c.scale(2-sq,sq);c.translate(-128,-214)
|
||||||
|
// battery body, level and cap
|
||||||
|
c.fillStyle='#868e96';c.lineWidth=7;c.beginPath();c.roundRect(108,44,40,18,5);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.roundRect(80,56,96,158,18);c.fill();c.stroke()
|
||||||
|
const H=138,top=206-H*L,col=t>=.72&&t<.97?'#ffd43b':L>.6?'#51cf66':L>.3?'#fcc419':'#ff6b6b'
|
||||||
|
if(!(dead&&i%4==3)){c.fillStyle=col;c.beginPath();c.roundRect(90,top,76,206-top,10);c.fill()}
|
||||||
|
c.lineWidth=7;c.beginPath();c.roundRect(80,56,96,158,18);c.stroke()
|
||||||
|
// face
|
||||||
|
c.fillStyle='#111';c.strokeStyle='#111';c.lineWidth=5
|
||||||
|
const ey=118,ex=[110,146]
|
||||||
|
if(t>=.72){for(const x of ex)c.beginPath(),c.arc(x,ey,7,PI*1.1,PI*1.9),c.stroke();c.beginPath();c.arc(128,140,8,.2*PI,.8*PI);c.stroke()}
|
||||||
|
else if(dead){for(const x of ex)c.beginPath(),c.moveTo(x-7,ey-7),c.lineTo(x+7,ey+7),c.moveTo(x+7,ey-7),c.lineTo(x-7,ey+7),c.stroke();c.beginPath();c.moveTo(118,146);c.quadraticCurveTo(123,140,128,146);c.quadraticCurveTo(133,152,138,146);c.stroke()}
|
||||||
|
else if(L>.7){for(const x of ex)c.beginPath(),c.arc(x,ey,6,0,T),c.fill();c.fillStyle='#fff';for(const x of ex)c.beginPath(),c.arc(x+2,ey-2,2,0,T),c.fill();c.fillStyle='#ff8787';c.beginPath();c.moveTo(112,136);c.quadraticCurveTo(128,160,144,136);c.closePath();c.fill();c.stroke()}
|
||||||
|
else if(L>.45){for(const x of ex)c.beginPath(),c.arc(x,ey,6,0,T),c.fill();c.beginPath();c.arc(128,134,12,.25*PI,.75*PI);c.stroke()}
|
||||||
|
else if(L>.2){for(const x of ex)c.beginPath(),c.arc(x,ey+2,6,0,T),c.fill();c.lineWidth=4;for(const x of ex)c.beginPath(),c.moveTo(x-9,ey-6),c.lineTo(x+9,ey-6),c.stroke();c.beginPath();c.moveTo(116,146);c.lineTo(140,146);c.stroke()
|
||||||
|
c.fillStyle='#74c0fc';c.lineWidth=4;c.beginPath();c.moveTo(166,92);c.quadraticCurveTo(173,104,166,108);c.quadraticCurveTo(159,104,166,92);c.fill();c.stroke()}
|
||||||
|
else{c.lineWidth=4;for(const x of ex)c.beginPath(),c.moveTo(x-8,ey),c.lineTo(x+8,ey),c.stroke();c.beginPath();c.arc(128,150,9,1.15*PI,1.85*PI);c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
// charging bolt and zzz
|
||||||
|
if(t>=.72&&t<.97){c.fillStyle='#ffd43b';c.lineWidth=5;c.beginPath();c.moveTo(134,166);c.lineTo(118,186);c.lineTo(128,186);c.lineTo(122,204);c.lineTo(140,182);c.lineTo(130,182);c.closePath();c.fill();c.stroke()
|
||||||
|
const z=(t-.72)/.25;c.lineWidth=4;for(const k of[0,1]){const q=(z+k*.5)%1,zx=190+q*20,zy=110-q*40,s=6+q*6;c.beginPath();c.moveTo(zx-s,zy-s);c.lineTo(zx+s,zy-s);c.lineTo(zx-s,zy+s);c.lineTo(zx+s,zy+s);c.stroke()}}
|
||||||
|
// speech bubbles hitting it
|
||||||
|
for(const[s,tb,x,y,d]of BUB){const k=pop((t-tb)/.06)*(t<.62?1:1-ease((t-.62)/.06));if(k<=0)continue
|
||||||
|
const w=s.length*11.4+14,e=d*(w/2-16);c.save();c.translate(x,y);c.scale(k,k);c.fillStyle='#fff';c.lineWidth=6
|
||||||
|
c.beginPath();c.moveTo(e-d*8,10);c.lineTo(e+d*22,30);c.lineTo(e+d*6,10);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(-w/2,-17,w,34,14);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.moveTo(e-d*5,8);c.lineTo(e+d*16,24);c.lineTo(e+d*4,8);c.fill()
|
||||||
|
txt(c,s,0,-6.5,2.1,null,3.5);c.restore()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
// a striped sock with googly eyes peeks out of the washing machine, hops down and tiptoes away with a little bindle (where socks go)
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=36,delay=75,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),lp=(a,b,u)=>a+(b-a)*u
|
||||||
|
const WALL='#c5f6fa',FLOOR='#99e9f2',WM='#f8f9fa',GL='#a5d8ff',SK='#fff',ST='#ff6b6b',BAS='#ffc078'
|
||||||
|
const SX=178,SY=140,R=42
|
||||||
|
const sockPath=c=>{c.beginPath();c.moveTo(-13,-74);c.lineTo(13,-74);c.lineTo(13,-22);c.quadraticCurveTo(14,-6,0,-6);c.lineTo(-30,-6);c.quadraticCurveTo(-42,-6,-42,-17);c.quadraticCurveTo(-42,-28,-30,-28);c.lineTo(-13,-28);c.closePath()}
|
||||||
|
const sock=(c,x,y,s,lean,step,lx,bindle)=>{
|
||||||
|
c.save();c.translate(x,y);c.scale(s,s);c.strokeStyle='#111'
|
||||||
|
for(const[d,k]of[[-26,0],[2,1]]){const up=max(0,sin(step+k*PI))*13;c.lineWidth=4;c.beginPath();c.moveTo(d,-8);c.lineTo(d-2,-up);c.stroke();c.fillStyle='#111';c.beginPath();c.ellipse(d-5,-up,5,3,0,0,T);c.fill()}
|
||||||
|
c.rotate(lean)
|
||||||
|
if(bindle){c.lineWidth=4;c.beginPath();c.moveTo(10,-46);c.lineTo(26,-54);c.stroke();c.beginPath();c.moveTo(-6,-38);c.lineTo(34,-84);c.stroke();c.fillStyle='#4dabf7';c.lineWidth=4;c.beginPath();c.arc(36,-90,11,0,T);c.fill();c.stroke();c.fillStyle='#fff';for(const[a,b]of[[33,-94],[40,-87],[33,-84]])c.beginPath(),c.arc(a,b,2,0,T),c.fill()}
|
||||||
|
c.lineWidth=6;sockPath(c);c.fillStyle=SK;c.fill();c.save();c.clip();c.fillStyle=ST;for(const y of[-62,-46,-30])c.fillRect(-50,y,70,8);c.fillStyle='#e9ecef';c.fillRect(-20,-74,40,8);c.restore();sockPath(c);c.stroke()
|
||||||
|
c.lineWidth=3;c.beginPath();c.moveTo(-13,-66);c.lineTo(13,-66);c.stroke()
|
||||||
|
for(const d of[-1,1]){c.fillStyle='#fff';c.lineWidth=3;c.beginPath();c.arc(d*7,-55,7,0,T);c.fill();c.stroke();c.fillStyle='#111';c.beginPath();c.arc(d*7+lx*3,-55+1,3.5,0,T);c.fill()}
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const pk=io(t/.1),look=t<.18?sin(T*cl((t-.06)/.12)):-1,jp=cl((t-.2)/.1),wk=cl((t-.32)/.62)
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=WALL;c.fill();c.clip()
|
||||||
|
c.fillStyle=FLOOR;c.fillRect(0,224,256,40);c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.moveTo(0,224);c.lineTo(256,224);c.stroke()
|
||||||
|
c.lineWidth=5;c.fillStyle='#fff';c.beginPath();c.rect(24,36,64,50);c.fill();c.stroke();c.fillStyle='#e7f5ff';c.beginPath();c.rect(30,42,52,38);c.fill();c.lineWidth=4;c.beginPath();c.moveTo(56,36);c.lineTo(56,86);c.moveTo(24,61);c.lineTo(88,61);c.stroke()
|
||||||
|
c.lineWidth=6;c.fillStyle=BAS;c.beginPath();c.moveTo(14,178);c.lineTo(86,178);c.lineTo(80,226);c.lineTo(20,226);c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#e8590c';c.lineWidth=4;c.beginPath();for(const x of[32,50,68])c.moveTo(x,186),c.lineTo(x,218);c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle='#fff';c.beginPath();c.moveTo(18,178);c.quadraticCurveTo(30,164,46,172);c.quadraticCurveTo(62,160,82,178);c.closePath();c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#111'
|
||||||
|
c.lineWidth=6;c.fillStyle=WM;c.beginPath();c.roundRect(118,52,124,176,10);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.moveTo(118,84);c.lineTo(242,84);c.stroke()
|
||||||
|
c.fillStyle='#ced4da';c.lineWidth=4;c.beginPath();c.arc(222,68,8,0,T);c.fill();c.stroke();c.fillStyle='#69db7c';c.beginPath();c.roundRect(132,62,40,12,3);c.fill();c.stroke()
|
||||||
|
c.lineWidth=7;c.fillStyle='#dee2e6';c.beginPath();c.arc(SX,SY+6,R+10,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#343a40';c.lineWidth=5;c.beginPath();c.arc(SX,SY+6,R,0,T);c.fill();c.stroke()
|
||||||
|
c.save();c.beginPath();c.arc(SX,SY+6,R-3,0,T);c.clip()
|
||||||
|
for(const[a,col]of[[.5,'#ffd43b'],[1.4,'#9775fa'],[2.4,'#69db7c']])c.fillStyle=col,c.lineWidth=4,c.beginPath(),c.ellipse(SX+26*cos(a+.15*sin(T*t)),SY+6+26*sin(a+.15*sin(T*t)),20,14,a,0,T),c.fill(),c.stroke()
|
||||||
|
if(t<.22)sock(c,SX+4,SY+64-50*pk,.9,0,0,look,0)
|
||||||
|
c.restore()
|
||||||
|
c.fillStyle=GL;c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.ellipse(SX-R-20,SY+6,13,R+6,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.beginPath();c.ellipse(SX-R-23,SY-10,3,14,0,0,T);c.fill()
|
||||||
|
if(t>=.22&&t<.32){const x=lp(SX+4,150,jp),y=lp(SY+10,224,jp)-60*sin(PI*jp),s=lp(.9,1.35,jp);sock(c,x,y,s,-.2*sin(PI*jp),0,-1,0)}
|
||||||
|
if(t>=.32){const x=lp(150,-80,wk),st=wk*T*5,y=224-4*abs(sin(st));sock(c,x,y,1.35,-.1+.06*sin(st),st,wk>.35&&wk<.55?1:-1,1)}
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// the cursor keeps opening new tabs until they're thin slivers, the laptop sweats, smokes, and finally crashes before rebooting with two tabs
|
||||||
|
const{sin,cos,PI,min,max,round}=Math,T=2*PI
|
||||||
|
const U=[0,...Array.from({length:10},(_,k)=>.06+k*.06),.64,.68,.92]
|
||||||
|
export const frames=U.length,delay=[500,...Array(10).fill(130),60,1100,200],rim=4
|
||||||
|
const cl=u=>min(1,max(0,u))
|
||||||
|
const K='#1b1b1f',FV=['#ff6b6b','#4dabf7','#ffd43b','#69db7c','#b197fc','#ff922b']
|
||||||
|
const puff=(c,x,y,r)=>{c.fillStyle='#dee2e6';c.strokeStyle=K;c.lineWidth=4;c.beginPath();for(const[a,b,s]of[[0,0,1],[-.8,.3,.75],[.8,.35,.7]])c.moveTo(x+a*r+r*s,y+b*r),c.arc(x+a*r,y+b*r,r*s,0,T);c.fill();c.stroke();c.fillStyle='#dee2e6';c.beginPath();c.arc(x,y,r-2,0,T);c.arc(x-.8*r,y+.3*r,.75*r-2,0,T);c.fill()}
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=U[i],dead=t>=.66&&t<.9,flash=t>=.62&&t<.66,n=t>=.9?1:t>.6?40:round(2*20**(t/.6)),heat=cl((t-.2)/.4)*(t<.9)
|
||||||
|
const sh=t>=.5&&t<.64?2*(i%2?1:-1):0
|
||||||
|
c.translate(0,14);c.save();c.translate(sh,0)
|
||||||
|
c.strokeStyle=K;c.lineWidth=6;c.lineJoin='round'
|
||||||
|
const hb=`rgb(${173+82*heat},${181-80*heat},${189-120*heat})`
|
||||||
|
c.fillStyle=hb;c.beginPath();c.moveTo(34,176);c.lineTo(222,176);c.lineTo(248,208);c.lineTo(8,208);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#868e96';c.beginPath();c.roundRect(104,188,48,10,4);c.fill()
|
||||||
|
c.fillStyle='#ced4da';c.beginPath();c.roundRect(24,24,208,154,12);c.fill();c.stroke()
|
||||||
|
const sx=36,sy=36,sw=184,sh2=130
|
||||||
|
if(dead){c.fillStyle='#343a40';c.fillRect(sx,sy,sw,sh2);c.strokeStyle='#fff';c.lineWidth=7
|
||||||
|
for(const x of[96,160]){c.beginPath();c.moveTo(x-12,82);c.lineTo(x+12,106);c.moveTo(x+12,82);c.lineTo(x-12,106);c.stroke()}
|
||||||
|
c.lineWidth=6;c.beginPath();c.moveTo(104,138);for(let k=1;k<=6;k++)c.lineTo(104+8*k,138+(k%2?-6:0));c.stroke()}
|
||||||
|
else if(flash){c.fillStyle='#fff';c.fillRect(sx,sy,sw,sh2)}
|
||||||
|
else{
|
||||||
|
c.fillStyle='#e9ecef';c.fillRect(sx,sy,sw,28)
|
||||||
|
const tw=(sw-30)/n;c.lineWidth=2
|
||||||
|
for(let k=n-1;k>=0;k--){const x=sx+3+k*tw,a=k==n-1;c.fillStyle=a?'#fff':'#ced4da';c.strokeStyle=K;c.beginPath();c.roundRect(x,sy+4,tw+(tw>8?2:0),24,[min(6,tw/2),min(6,tw/2),0,0]);c.fill();c.stroke()
|
||||||
|
if(tw>12){c.fillStyle=FV[k%6];c.beginPath();c.arc(x+min(10,tw/2),sy+16,4.5,0,T);c.fill()}
|
||||||
|
if(tw>30){c.fillStyle='#868e96';c.fillRect(x+18,sy+14,tw-28,4)}}
|
||||||
|
c.strokeStyle=K;c.lineWidth=3;c.beginPath();c.moveTo(sx+sw-14,sy+9);c.lineTo(sx+sw-14,sy+23);c.moveTo(sx+sw-21,sy+16);c.lineTo(sx+sw-7,sy+16);c.stroke()
|
||||||
|
c.fillStyle='#fff';c.fillRect(sx,sy+28,sw,sh2-28)
|
||||||
|
c.fillStyle='#f1f3f5';c.beginPath();c.roundRect(sx+8,sy+33,sw-16,11,5);c.fill()
|
||||||
|
c.fillStyle=FV[(n-1)%6];c.globalAlpha=.5;c.fillRect(sx+10,sy+50,70,54);c.globalAlpha=1
|
||||||
|
c.fillStyle='#ced4da';for(const[y,w]of[[54,80],[66,70],[78,84],[90,60],[112,150],[122,130]])c.fillRect(sx+(y<100?90:10),sy+y,w,6)
|
||||||
|
}
|
||||||
|
c.strokeStyle=K;c.lineWidth=5;c.strokeRect(sx,sy,sw,sh2)
|
||||||
|
c.restore()
|
||||||
|
// cursor clicking the new tab button
|
||||||
|
if(t>0&&t<.62){const p=i%2,x=sx+sw-12+sh,y=sy+18+(p?2:0);c.save();c.translate(x,y);c.scale(p?.9:1,p?.9:1);c.fillStyle='#fff';c.strokeStyle=K;c.lineWidth=3.5
|
||||||
|
c.beginPath();c.moveTo(0,0);c.lineTo(0,26);c.lineTo(7,20);c.lineTo(12,31);c.lineTo(17,29);c.lineTo(12,18);c.lineTo(21,18);c.closePath();c.fill();c.stroke();c.restore()
|
||||||
|
if(p){c.strokeStyle=K;c.lineWidth=3;for(const a of[-2.4,-1.6,-.8])c.beginPath(),c.moveTo(x+10*cos(a),y+10*sin(a)),c.lineTo(x+17*cos(a),y+17*sin(a)),c.stroke()}}
|
||||||
|
// sweat and smoke as the tabs pile up
|
||||||
|
if(t>=.3&&t<.66){c.fillStyle='#74c0fc';c.strokeStyle=K;c.lineWidth=3;for(const[x,d]of[[24,-1],[232,1]]){const u=(t*5+(d>0?.5:0))%1;c.save();c.translate(x+d*14*u,40+30*u);c.rotate(d*.5);c.beginPath();c.moveTo(0,-10);c.quadraticCurveTo(8,2,0,6);c.quadraticCurveTo(-8,2,0,-10);c.fill();c.stroke();c.restore()}}
|
||||||
|
if(t>=.42&&t<.9){const s=dead?1.4:cl((t-.4)/.2);puff(c,206+sh,22-6*s,10+8*s);if(s>.5||dead)puff(c,182,14-4*s,8+5*s)}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// blob in profile with eyes shut in mock sorrow saws away at a teeny tiny violin, pinky up, sad little notes drifting off ("world's smallest violin")
|
||||||
|
const{sin,cos,PI,max,min}=Math,T=2*PI
|
||||||
|
export const frames=16,delay=100,rim=5
|
||||||
|
const Y='#ffd43b',BL='#ff8787',VW='#e8803a',VD='#9c4a1a',NT='#4dabf7',TR='#74c0fc'
|
||||||
|
const note=(c,x,y,s,a,two)=>{c.save();c.translate(x,y);c.rotate(a);c.scale(s,s)
|
||||||
|
for(const[w,st]of[[12,'#111'],[5,NT]]){c.lineWidth=w;c.strokeStyle=st;c.beginPath();c.moveTo(6,4);c.lineTo(6,-22);if(two)c.lineTo(22,-26),c.lineTo(22,0);else c.quadraticCurveTo(10,-14,18,-12);c.stroke()}
|
||||||
|
c.strokeStyle='#111';c.fillStyle=NT;c.lineWidth=4
|
||||||
|
for(const x of two?[0,16]:[0])c.beginPath(),c.ellipse(x,4,7.5,5.5,-.4,0,T),c.fill(),c.stroke()
|
||||||
|
c.restore()}
|
||||||
|
export default(c,t)=>{
|
||||||
|
const b=sin(t*T*2)
|
||||||
|
c.translate(150,132);c.scale(1.22,1.22);c.translate(-180,-120);c.lineWidth=6.5
|
||||||
|
// body, facing right
|
||||||
|
c.fillStyle=Y;c.beginPath();c.moveTo(22,240);c.bezierCurveTo(14,120,50,56,108,56);c.bezierCurveTo(166,56,190,110,184,240);c.closePath();c.fill();c.stroke()
|
||||||
|
// face: shut eye with lashes, worried brow, wobbly pout, a tear rolling down
|
||||||
|
c.lineWidth=5;c.beginPath();c.arc(142,104,13,.1*PI,.9*PI);c.stroke()
|
||||||
|
c.lineWidth=3.5;c.beginPath();for(const k of[-.7,-.1,.5])c.moveTo(142+sin(k)*13,104+cos(k)*13),c.lineTo(142+sin(k)*19,104+cos(k)*19);c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();c.moveTo(128,88);c.quadraticCurveTo(142,86,154,78);c.stroke()
|
||||||
|
c.fillStyle=BL;c.beginPath();c.ellipse(150,134,12,6,0,0,T);c.fill()
|
||||||
|
c.lineWidth=4.5;c.beginPath();for(let x=-8;x<=8;x+=2)c.lineTo(170+x,146-(x*x)/-24-3+1.2*sin(x+t*T*4));c.stroke()
|
||||||
|
const tp=(t*2)%1,tx=136-tp*4,ty=124+tp*34;c.fillStyle=TR;c.lineWidth=3.5;c.beginPath();c.moveTo(tx,ty-8);c.quadraticCurveTo(tx+6,ty+2,tx,ty+4);c.quadraticCurveTo(tx-6,ty+2,tx,ty-8);c.fill();c.stroke()
|
||||||
|
// the teeny violin under the chin
|
||||||
|
c.save();c.translate(200,164);c.rotate(.12)
|
||||||
|
c.lineWidth=4.5;c.fillStyle='#343a40';c.beginPath();c.roundRect(2,-3.5,26,7,3.5);c.fill();c.stroke()
|
||||||
|
c.fillStyle=VD;c.beginPath();c.arc(32,-1,5.5,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=VW;c.beginPath();c.moveTo(-18,0);c.bezierCurveTo(-18,-13,-7,-13,-5,-7);c.bezierCurveTo(-3,-11,9,-12,9,0);c.bezierCurveTo(9,12,-3,11,-5,7);c.bezierCurveTo(-7,13,-18,13,-18,0);c.closePath();c.fill();c.stroke()
|
||||||
|
c.lineWidth=2.5;c.beginPath();c.moveTo(-12,-6);c.quadraticCurveTo(-9,-4,-11,-1);c.moveTo(-12,6);c.quadraticCurveTo(-9,4,-11,1);c.stroke()
|
||||||
|
c.lineWidth=3.5;c.beginPath();c.moveTo(-4,-6);c.lineTo(-4,6);c.stroke()
|
||||||
|
c.restore()
|
||||||
|
// bow sliding across the strings, hand with its pinky up
|
||||||
|
const ux=cos(1.95),uy=sin(1.95),o=-12+22*b,bx=198+ux*o,by=163+uy*o
|
||||||
|
for(const[w,s]of[[8,'#111'],[3,'#f1f3f5']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(bx-ux*26,by-uy*26),c.lineTo(bx+ux*44,by+uy*44),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=2.5;c.beginPath();c.moveTo(bx-ux*26+4,by-uy*26+1);c.lineTo(bx+ux*40+4,by+uy*40+1);c.stroke()
|
||||||
|
const hx=bx+ux*50,hy=by+uy*50
|
||||||
|
c.lineWidth=6;c.fillStyle=Y;c.beginPath();c.ellipse(hx,hy,13,12,0,0,T);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.roundRect(hx+8,hy-20,7,14,3.5);c.fill();c.stroke()
|
||||||
|
// sad notes drifting up and away
|
||||||
|
for(let k=0;k<3;k++){const p=(t+k/3)%1,s=min(1,p*6)*(1-max(0,p-.8)*5)
|
||||||
|
if(s>.05)note(c,212+p*12+6*sin(p*T*1.5+k),140-p*96,s*.75,.3*sin(p*T+k),k==1)}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// screen-pale hoodie gremlin with its phone slowly reaches out and pokes a tuft of grass, jolts back in shock, then works up the nerve to try again
|
||||||
|
const{sin,cos,PI,max,min}=Math,T=2*PI
|
||||||
|
export const frames=24,delay=80,rim=5
|
||||||
|
const HD='#5c5f66',HL='#3d4045',SK='#dbe9f6',BAG='#b197fc',GR='#51cf66',GD='#2f9e44',DT='#a9744f',PH='#74c0fc'
|
||||||
|
const ez=(t,a,b)=>{const x=min(1,max(0,(t-a)/(b-a)));return x*x*(3-2*x)}
|
||||||
|
const spark=(c,x,y,s)=>{c.fillStyle='#ffe066';c.lineWidth=3.5;c.beginPath();for(let k=0;k<8;k++){const r=k%2?s*.3:s,a=k*PI/4;c.lineTo(x+cos(a)*r,y+sin(a)*r)}c.closePath();c.fill();c.stroke()}
|
||||||
|
const BLADES=[[-26,-34,-.5],[-14,-58,-.25],[-2,-44,0],[10,-62,.15],[22,-40,.4],[30,-52,.6]]
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
// idle on phone, glance at the grass, slow reach, ZAP at .5, recoil, shiver, back to the phone
|
||||||
|
const reach=ez(t,.18,.5)-ez(t,.62,.68),zap=t>=.5&&t<.62,rec=t>=.62&&t<.86,lean=zap?0:rec?-10*(1-ez(t,.72,.86)):0,shake=zap?2.5*sin(i*2.5):0
|
||||||
|
const look=t<.1||t>=.86?0:1,bend=zap?1:0
|
||||||
|
// sun
|
||||||
|
c.fillStyle='#ffd43b';c.lineWidth=5;c.beginPath();c.arc(222,36,18,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();for(let k=0;k<8;k++){const a=k*PI/4;c.moveTo(222+cos(a)*26,36+sin(a)*26);c.lineTo(222+cos(a)*34,36+sin(a)*34)}c.stroke()
|
||||||
|
// grass
|
||||||
|
const gx=204,gy=232
|
||||||
|
c.fillStyle=DT;c.beginPath();c.ellipse(gx,gy,46,14,0,PI,T);c.closePath();c.fill();c.stroke()
|
||||||
|
for(const[k,[x,h,a]]of BLADES.entries()){const sw=k==1?-bend*.55:bend?.08*sin(i*3+k):0
|
||||||
|
c.save();c.translate(gx+x,gy-6);c.rotate(a*.5+sw)
|
||||||
|
c.fillStyle=k%2?GR:'#69db7c';c.lineWidth=5;c.beginPath();c.moveTo(-7,4);c.quadraticCurveTo(-6,h*.5,0,h);c.quadraticCurveTo(6,h*.5,7,4);c.closePath();c.fill();c.stroke();c.restore()}
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4;for(let k=0;k<5;k++){const a=k*T/5;c.beginPath();c.ellipse(gx+34+cos(a)*7,gy-46+sin(a)*7,5,3.5,a,0,T);c.fill();c.stroke()}
|
||||||
|
c.fillStyle='#ffd43b';c.beginPath();c.arc(gx+34,gy-46,5,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=4;c.strokeStyle=GD;c.beginPath();c.moveTo(gx+34,gy-40);c.quadraticCurveTo(gx+30,gy-22,gx+32,gy-8);c.stroke();c.strokeStyle='#111'
|
||||||
|
// gremlin
|
||||||
|
c.save();c.translate(shake+lean,0)
|
||||||
|
c.lineWidth=7;c.fillStyle=HD;c.beginPath();c.moveTo(14,240);c.bezierCurveTo(8,168,36,148,88,148);c.bezierCurveTo(140,148,162,180,156,240);c.closePath();c.fill();c.stroke()
|
||||||
|
c.save();c.translate(86,106);c.rotate(zap?-.06:rec?-.1*(1-ez(t,.72,.86)):0)
|
||||||
|
c.fillStyle=HD;c.beginPath();c.ellipse(0,0,70,64,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle=HL;c.beginPath();c.ellipse(6,8,54,48,0,0,T);c.fill()
|
||||||
|
c.fillStyle=SK;c.lineWidth=6;c.beginPath();c.ellipse(8,12,47,41,0,0,T);c.fill();c.stroke()
|
||||||
|
const hu=zap?10:0;c.lineWidth=5;c.beginPath();c.moveTo(-16,-24);c.lineTo(-8,-38-hu);c.lineTo(0,-24);c.lineTo(8,-42-hu);c.lineTo(16,-24);c.lineTo(22,-36-hu);c.lineTo(26,-24);c.closePath();c.fill();c.stroke()
|
||||||
|
// face: glazed eyes with dark bags, on the phone or on the grass
|
||||||
|
const lx=zap?0:look?6:-3,ly=zap?0:look?1:6
|
||||||
|
for(const d of[-1,1]){const x=8+d*19,y=8
|
||||||
|
c.strokeStyle=BAG;c.lineWidth=4;c.beginPath();c.arc(x,y+5,13,.2*PI,.8*PI);c.stroke();c.strokeStyle='#111'
|
||||||
|
c.fillStyle='#fff';c.lineWidth=4.5;const er=zap?15:12;c.beginPath();c.ellipse(x,y,er,er*(zap?1.1:.92),0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.arc(x+lx,y+ly,zap?2.5:4.5,0,T);c.fill()}
|
||||||
|
c.lineWidth=4.5
|
||||||
|
if(zap)c.fillStyle='#c92a2a',c.beginPath(),c.ellipse(10,38,7,8,0,0,T),c.fill(),c.stroke()
|
||||||
|
else if(rec)c.beginPath(),c.moveTo(-2,38),c.lineTo(4,35),c.lineTo(10,38),c.lineTo(16,35),c.lineTo(22,38),c.stroke()
|
||||||
|
else{c.beginPath();c.moveTo(0,38);c.quadraticCurveTo(10,34,20,38);c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
// phone in the near hand
|
||||||
|
c.save();c.translate(64,192);c.rotate(-.3)
|
||||||
|
c.fillStyle='#212529';c.lineWidth=5;c.beginPath();c.roundRect(-15,-26,30,46,6);c.fill();c.stroke()
|
||||||
|
c.fillStyle=PH;c.beginPath();c.roundRect(-10,-20,20,34,3);c.fill()
|
||||||
|
c.restore()
|
||||||
|
c.fillStyle=SK;c.lineWidth=5;c.beginPath();c.ellipse(70,210,13,11,0,0,T);c.fill();c.stroke()
|
||||||
|
// reaching arm with one pointer finger
|
||||||
|
const hx=130+54*reach,hy=208-16*reach
|
||||||
|
for(const[w,s]of[[30,'#111'],[17,HD]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(124,174),c.quadraticCurveTo(128+22*reach,188-6*reach,hx-10,hy),c.stroke()
|
||||||
|
c.strokeStyle='#111';c.fillStyle=SK;c.lineWidth=5
|
||||||
|
c.save();c.translate(hx,hy);c.rotate(-.3*reach)
|
||||||
|
c.beginPath();c.roundRect(-4,-5,10+16*reach,10,5);c.fill();c.stroke()
|
||||||
|
c.beginPath();c.ellipse(-4,3,12,11,0,0,T);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
if(rec)for(const[w,s]of[[9,'#111'],[3.5,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();for(const y of[60,80,100])c.moveTo(166,y),c.lineTo(178,y-4);c.stroke()}
|
||||||
|
c.restore();c.strokeStyle='#111'
|
||||||
|
if(zap){const p=ez(t,.5,.56);for(let k=0;k<5;k++){const a=k*T/5+.4;spark(c,192+cos(a)*(16+18*p),186+sin(a)*(14+16*p),13-4*p)}
|
||||||
|
for(const[w,s]of[[15,'#111'],[7,'#ff6b6b']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.moveTo(160,16);c.lineTo(156,48);c.moveTo(154,66);c.lineTo(154,66);c.stroke()}c.strokeStyle='#111'}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// a hand bumps a coffee mug, it tips and floods the laptop, the screen dies, then the whole thing rewinds like ctrl+z
|
||||||
|
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||||
|
export const frames=40,delay=70,rim=3
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2)
|
||||||
|
const WALL='#ffe3c2',TOP='#d9a066',EDGE='#a86b3c',MUG='#4dabf7',COF='#6b3f22',CL='#8a5530',LAP='#ced4da',LAPD='#adb5bd',SCR='#e7f5ff',SL='#4dabf7',SLV='#ff922b',SKIN='#ffd3b0'
|
||||||
|
const PX=80,PY=216
|
||||||
|
const mug=(c,a)=>{
|
||||||
|
c.save();c.translate(PX,PY);c.rotate(a);c.lineWidth=6
|
||||||
|
c.fillStyle=MUG;c.beginPath();c.arc(-46,-28,13,0,T);c.stroke()
|
||||||
|
c.beginPath();c.moveTo(-44,-54);c.lineTo(-44,-8);c.quadraticCurveTo(-44,0,-36,0);c.lineTo(-8,0);c.quadraticCurveTo(0,0,0,-8);c.lineTo(0,-54);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle=COF;c.lineWidth=5;c.beginPath();c.ellipse(-22,-54,22,6,0,0,T);c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.moveTo(-34,-42);c.lineTo(-34,-18);c.stroke()
|
||||||
|
c.fillStyle='#fff';c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.moveTo(-22,-36);c.bezierCurveTo(-34,-46,-38,-28,-22,-18);c.bezierCurveTo(-6,-28,-10,-46,-22,-36);c.fill();c.stroke()
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
const scr=(c,g,i)=>{
|
||||||
|
c.save();c.beginPath();c.rect(146,108,86,70);c.clip()
|
||||||
|
if(g<.35){c.fillStyle=SCR;c.fillRect(146,108,86,70);c.strokeStyle=SL;c.lineWidth=5;for(const[y,w]of[[124,52],[138,64],[152,40],[166,58]])c.beginPath(),c.moveTo(156,y),c.lineTo(156+w,y),c.stroke()}
|
||||||
|
else if(g<.75){const P=['#ff6b6b','#51cf66','#cc5de8','#fcc419','#4dabf7','#fff'];for(let k=0;k<7;k++)c.fillStyle=P[(k+i)%6],c.fillRect(146+((k*37+i*23)%17)-8,108+k*10,100,10)}
|
||||||
|
else{c.fillStyle='#343a40';c.fillRect(146,108,86,70);c.strokeStyle='#fff';c.lineWidth=5
|
||||||
|
for(const d of[-1,1])c.beginPath(),c.moveTo(189+d*16-5,130),c.lineTo(189+d*16+5,140),c.moveTo(189+d*16+5,130),c.lineTo(189+d*16-5,140),c.stroke()
|
||||||
|
c.beginPath();c.arc(189,168,13,PI*1.15,PI*1.85);c.stroke()}
|
||||||
|
c.restore()
|
||||||
|
}
|
||||||
|
const undo=(c,s)=>{
|
||||||
|
c.save();c.strokeStyle='#111';c.translate(52,50);c.scale(s,s);c.lineWidth=6;c.fillStyle='#fff';c.beginPath();c.arc(0,0,30,0,T);c.fill();c.stroke()
|
||||||
|
c.lineWidth=7;c.beginPath();c.arc(2,4,13,PI*1.05,PI*.35,false);c.stroke()
|
||||||
|
c.fillStyle='#111';c.beginPath();c.moveTo(-20,2);c.lineTo(-3,-1);c.lineTo(-16,-14);c.closePath();c.fill();c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
const u=t<.54?t/.54:t<.62?1:t<.86?1-io((t-.62)/.24):0,rw=t>.6&&t<.88
|
||||||
|
const hx=u<.2?-40+76*io(u/.2):36-80*io((u-.22)/.2),p=cl((u-.2)/.2),a=PI/2*p*p-.1*sin(PI*cl((u-.4)/.08))+.06*sin(PI*cl((u-.17)/.05))
|
||||||
|
const s=cl((u-.32)/.3),g=cl((u-.5)/.4)
|
||||||
|
c.save();c.beginPath();c.roundRect(6,6,244,244,28);c.fillStyle=WALL;c.fill();c.clip()
|
||||||
|
c.fillStyle=TOP;c.fillRect(0,150,256,110);c.strokeStyle=EDGE;c.lineWidth=4;c.beginPath();for(const y of[172,198,232])c.moveTo(0,y),c.lineTo(256,y);c.stroke()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.moveTo(0,150);c.lineTo(256,150);c.stroke()
|
||||||
|
c.lineWidth=6;c.fillStyle=LAP;c.beginPath();c.roundRect(138,98,102,92,8);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#111';c.fillRect(146,108,86,70);scr(c,g,i)
|
||||||
|
c.fillStyle=LAPD;c.beginPath();c.moveTo(140,190);c.lineTo(238,190);c.lineTo(250,228);c.lineTo(128,228);c.closePath();c.fill();c.stroke()
|
||||||
|
c.lineWidth=3;c.beginPath();for(let k=0;k<3;k++){const y=197+k*8,l=142-k*3;c.moveTo(l,y);c.lineTo(236+k*3,y)}for(let k=0;k<8;k++)c.moveTo(150+k*12,195),c.lineTo(147+k*12,219);c.stroke()
|
||||||
|
c.lineWidth=5;c.beginPath();c.roundRect(170,220,38,6,3);c.stroke()
|
||||||
|
if(s>0){
|
||||||
|
const B=[[122+30*s,215,12+40*s,5+9*s],[164+36*s,211,4+34*s,3+8*s],[200+26*s,205,2+22*s,2+6*s],[150+40*s,222,3+20*s,2+5*s]]
|
||||||
|
c.fillStyle='#111';for(const[x,y,a,b]of B)c.beginPath(),c.ellipse(x,y,a+5,b+5,0,0,T),c.fill()
|
||||||
|
c.fillStyle=COF;for(const[x,y,a,b]of B)c.beginPath(),c.ellipse(x,y,a,b,0,0,T),c.fill()
|
||||||
|
c.fillStyle=CL;for(const[x,y,a,b]of B.slice(0,3))c.beginPath(),c.ellipse(x-a*.25,y-b*.3,a*.45,b*.3,0,0,T),c.fill()
|
||||||
|
c.fillStyle=COF;c.strokeStyle='#111';c.lineWidth=4
|
||||||
|
for(let k=0;k<6;k++){const q=cl(s*1.8-k*.15);if(q<=0||q>=1)continue;const x=132+(24+k*18)*q,y=192-(34+k*8)*sin(PI*q)+18*q;c.beginPath();c.arc(x,y,7-k*.6,0,T);c.fill();c.stroke()}
|
||||||
|
}
|
||||||
|
mug(c,a)
|
||||||
|
if(u<.22&&!rw){c.strokeStyle='#111';c.lineWidth=4;for(const k of[0,1]){const o=(t*3+k*.5)%1;c.globalAlpha=sin(PI*o);c.beginPath();c.moveTo(48+k*16,150-o*30);c.bezierCurveTo(56+k*16,140-o*30,40+k*16,128-o*30,48+k*16,118-o*30);c.stroke()}c.globalAlpha=1}
|
||||||
|
if(g>.2&&g<.8){c.strokeStyle='#ffd43b';c.lineWidth=5;for(const[x,y,r]of[[150,190,-.6],[226,186,.5],[196,182,0]]){c.save();c.translate(x,y);c.rotate(r+.3*sin(i*2));c.beginPath();c.moveTo(0,0);c.lineTo(-5,-10);c.lineTo(4,-12);c.lineTo(-2,-24);c.stroke();c.restore()}}
|
||||||
|
if(hx>-40){
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=SLV;c.beginPath();c.roundRect(hx-110,156,86,40,10);c.fill();c.stroke()
|
||||||
|
c.fillStyle=SKIN;c.beginPath();c.moveTo(hx-28,160);c.lineTo(hx-4,160);c.quadraticCurveTo(hx+8,160,hx+8,168);c.quadraticCurveTo(hx+8,176,hx-4,176);c.quadraticCurveTo(hx+4,184,hx-4,192);c.lineTo(hx-28,192);c.closePath();c.fill();c.stroke()
|
||||||
|
c.lineWidth=3;c.beginPath();c.moveTo(hx-14,176);c.lineTo(hx-4,176);c.moveTo(hx-14,184);c.lineTo(hx-6,184);c.stroke()
|
||||||
|
}
|
||||||
|
if(rw){
|
||||||
|
c.fillStyle='rgba(255,255,255,.35)';for(const k of[0,1,2])c.fillRect(0,(i*41+k*83)%256,256,10+k*4)
|
||||||
|
undo(c,1+.08*sin(T*t*8))
|
||||||
|
c.fillStyle='#111';for(const d of[0,1])c.beginPath(),c.moveTo(200+d*20,30),c.lineTo(220+d*20,18),c.lineTo(220+d*20,42),c.closePath(),c.fill()
|
||||||
|
}
|
||||||
|
c.restore();c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.roundRect(6,6,244,244,28);c.stroke()
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
// a VIBE CHECK gauge scans with its needle twitching all over, then slams into the top of the scale and the display flashes IMMACULATE
|
||||||
|
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||||
|
export const frames=30,delay=80,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)},pop=u=>(u=cl(u),u<.6?1.2*u/.6:1.2-.2*(u-.6)/.4)
|
||||||
|
const G={V:'004c80',I:'0040 202c 0c4c',B:'0c006082846606 66888a6c0c',E:'80000c8c 0666'," ":'',C:'826020020a2c6c8a',H:'000c 808c 0686',K:'000c 8007 358c',M:'0c0056a0ac',A:'0c0440848c 0787',U:'000a2c6c8a80',L:'000c8c',T:'0080 404c',".":'0c0c'}
|
||||||
|
const txt=(c,s,x,y,h,f='#fff',b='#111')=>{const k=h/12,P=[...s].map(ch=>(G[ch]||'').split(' ').filter(Boolean).map(q=>q.match(/../g).map(p=>[parseInt(p[0],36),parseInt(p[1],36)])));let w=-5;const X=P.map(g=>{const o=w+5;w=o+(g.length?max(...g.flat().map(p=>p[0])):3);return o})
|
||||||
|
c.save();c.translate(x-w*k/2,y-h/2);c.scale(k,k);for(const[l,s]of[[7,b],[3,f]]){c.lineWidth=l;c.strokeStyle=s;c.beginPath();P.forEach((g,i)=>g.forEach(q=>q.forEach(([a,b],j)=>c[j?'lineTo':'moveTo'](X[i]+a,b))));c.stroke()}c.restore()}
|
||||||
|
const CX=128,CY=156,R=96,ZONES=['#ff6b6b','#ffa94d','#ffd43b','#69db7c','#f06595']
|
||||||
|
const star=(c,x,y,s)=>{if(s<=0)return;c.save();c.translate(x,y);c.scale(s,s);c.fillStyle='#fff';c.lineWidth=3/s;c.beginPath();for(let k=0;k<8;k++){const r=k%2?4:14,a=k*PI/4-PI/2;c.lineTo(r*cos(a),r*sin(a))}c.closePath();c.fill();c.stroke();c.restore()}
|
||||||
|
export default(c,t,i)=>{
|
||||||
|
// needle angle from 0 (far left) to 1 (far right)
|
||||||
|
const scan=.4+.3*sin(t*T*5.3-1.4)+.16*sin(t*T*12.1+1)+.06*sin(t*T*23),slam=ez(t,.44,.5),home=ez(t,.86,.98)
|
||||||
|
let a=t<.06?.06:t<.44?.06+(scan-.06)*ez(t,.06,.12):.06+(scan-.06)*(1-slam)+.96*slam
|
||||||
|
if(t>=.5&&t<.86)a=.985+((i>>1)%2?0:.01)
|
||||||
|
if(t>=.86)a=.985+(.06-.985)*home
|
||||||
|
const done=t>=.5&&t<.9
|
||||||
|
// housing and dial
|
||||||
|
c.fillStyle='#9775fa';c.lineWidth=7;c.beginPath();c.arc(CX,CY,R+16,PI,0);c.lineTo(CX+R+16,CY+56);c.quadraticCurveTo(CX+R+16,CY+72,CX+R,CY+72);c.lineTo(CX-R,CY+72);c.quadraticCurveTo(CX-R-16,CY+72,CX-R-16,CY+56);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.arc(CX,CY,R,PI,0);c.closePath();c.fill();c.stroke()
|
||||||
|
c.lineCap='butt';ZONES.forEach((z,k)=>{c.strokeStyle=z;c.lineWidth=22;c.beginPath();c.arc(CX,CY,R-18,PI+k*PI/5,PI+(k+1)*PI/5);c.stroke()})
|
||||||
|
c.strokeStyle='#111';c.lineWidth=3;c.beginPath();c.arc(CX,CY,R-7,PI,0);c.stroke();c.beginPath();c.arc(CX,CY,R-29,PI,0);c.stroke()
|
||||||
|
for(let k=1;k<5;k++){const q=PI+k*PI/5;c.beginPath();c.moveTo(CX+(R-29)*cos(q),CY+(R-29)*sin(q));c.lineTo(CX+(R-7)*cos(q),CY+(R-7)*sin(q));c.stroke()}
|
||||||
|
c.lineCap='round'
|
||||||
|
// little faces on the ends of the scale
|
||||||
|
c.lineWidth=3;c.fillStyle='#111';for(const[x,s]of[[CX-56,-1],[CX+56,1]]){const y=CY-22;for(const d of[-1,1])c.beginPath(),c.arc(x+d*5,y-4,2,0,T),c.fill();c.beginPath();c.arc(x,y+(s<0?8:0),6,s<0?1.15*PI:.15*PI,s<0?1.85*PI:.85*PI);c.stroke()}
|
||||||
|
// display
|
||||||
|
c.fillStyle='#212529';c.lineWidth=5;c.beginPath();c.roundRect(CX-98,CY+14,196,44,10);c.fill();c.stroke()
|
||||||
|
if(done){if((i>>1)%3!=2)txt(c,'IMMACULATE',CX,CY+36,17,'#8ce99a','#2b8a3e')}
|
||||||
|
else{const n=1+(i>>1)%3;txt(c,'.'.repeat(n),CX,CY+40,16,'#8ce99a','#2b8a3e')}
|
||||||
|
// needle
|
||||||
|
const q=PI+a*PI;c.save();c.translate(CX,CY);c.rotate(q);c.fillStyle='#fa5252';c.lineWidth=4;c.beginPath();c.moveTo(R-14,0);c.lineTo(0,-8);c.lineTo(-10,0);c.lineTo(0,8);c.closePath();c.fill();c.stroke();c.restore()
|
||||||
|
c.fillStyle='#343a40';c.lineWidth=5;c.beginPath();c.arc(CX,CY,12,0,T);c.fill();c.stroke()
|
||||||
|
txt(c,'VIBE CHECK',CX,22,20,'#fff')
|
||||||
|
if(done){const u=(2*(i>>1)/frames-.5)/.4;for(const[x,y,o]of[[24,64,0],[234,70,.33],[18,118,.6],[238,124,.15],[214,96,.8],[44,92,.45]]){const p=(u*2+o)%1;star(c,x,y,sin(PI*p)*1.1)}}
|
||||||
|
if(t>=.5&&t<.56){c.lineWidth=5;for(const k of[-.5,-.25,0])c.beginPath(),c.moveTo(CX+(R+24)*cos(k),CY-30+(R+24)*sin(k)*.8),c.lineTo(CX+(R+40)*cos(k),CY-30+(R+40)*sin(k)*.8),c.stroke()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// a little guy leans over a dark pit, two huge eyes blink open down in the dark and stare back, he backs away sweating, then creeps back for another look
|
||||||
|
const{sin,cos,PI,min,max,hypot}=Math,T=2*PI
|
||||||
|
export const frames=32,delay=90,rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),ez=(t,a,b)=>{const x=cl((t-a)/(b-a));return x*x*(3-2*x)},bump=(t,a,w)=>cl(1-Math.abs(t-a)/w)
|
||||||
|
const PX=158,PY=184,K=1.5
|
||||||
|
const eye=(c,x,y,o,gx,gy)=>{
|
||||||
|
if(o<.05)return c.lineWidth=4,c.strokeStyle='#343a40',c.beginPath(),c.moveTo(x-18,y),c.quadraticCurveTo(x,y+5,x+18,y),c.stroke()
|
||||||
|
c.save();c.beginPath();c.moveTo(x-21,y);c.quadraticCurveTo(x,y-30*o,x+21,y);c.quadraticCurveTo(x,y+30*o,x-21,y);c.closePath();c.fillStyle='#fff';c.fill();c.clip()
|
||||||
|
const d=hypot(gx-x,gy-y),px=x+(gx-x)/d*8,py=y+(gy-y)/d*6;c.fillStyle="#111";c.beginPath();c.arc(px,py,7.5,0,T);c.fill();c.fillStyle="#fff";c.beginPath();c.arc(px-2.5,py-2.5,2.2,0,T);c.fill();c.restore()
|
||||||
|
}
|
||||||
|
export default(c,t)=>{
|
||||||
|
c.translate(0,-16)
|
||||||
|
const back=ez(t,.34,.6)-ez(t,.8,.97),gx=70-8*back,walk=(t>.34&&t<.6)||(t>.8&&t<.97),st=walk?sin(t*T*9):0
|
||||||
|
const shock=ez(t,.25,.28)*(1-ez(t,.7,.8)),lean=.42*(1-ez(t,.24,.27))-.16*shock+.42*ez(t,.9,.99)
|
||||||
|
const blink=1-bump(t,.47,.035),o1=(ez(t,.12,.15)-ez(t,.66,.73))*blink,o2=(ez(t,.17,.2)-ez(t,.68,.75))*blink
|
||||||
|
// island
|
||||||
|
c.fillStyle='#c08a5b';c.lineWidth=6;c.beginPath();c.moveTo(6,178);c.lineTo(6,196);c.ellipse(128,196,122,56,0,PI,0,true);c.lineTo(250,178);c.closePath();c.fill();c.stroke()
|
||||||
|
c.fillStyle='#8ce99a';c.beginPath();c.ellipse(128,178,122,56,0,0,T);c.fill();c.stroke()
|
||||||
|
c.strokeStyle='#37b24d';c.lineWidth=3.5;for(const[x,y]of[[28,184],[56,214],[106,226],[230,190],[216,150],[92,138],[150,130]])c.beginPath(),c.moveTo(x-5,y-7),c.lineTo(x,y),c.lineTo(x+5,y-8),c.stroke()
|
||||||
|
// pit with its far wall showing
|
||||||
|
c.save();c.beginPath();c.ellipse(PX,PY,78,36,0,0,T);c.fillStyle='#a9784f';c.fill();c.clip();c.fillStyle='#111';c.beginPath();c.ellipse(PX,PY+12,80,36,0,0,T);c.fill();c.restore()
|
||||||
|
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.ellipse(PX,PY,78,36,0,0,T);c.stroke()
|
||||||
|
// the eyes look at his head
|
||||||
|
const hx=gx+sin(lean)*66,hy=166-cos(lean)*66
|
||||||
|
eye(c,PX-26,PY+10,o1,hx,hy);eye(c,PX+26,PY+10,o2,hx,hy)
|
||||||
|
// little guy, feet at (gx,166), facing right
|
||||||
|
c.save();c.translate(gx,166);c.scale(K,K);c.rotate(lean);c.strokeStyle='#111'
|
||||||
|
c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.moveTo(d*7,-14),c.lineTo(d*7+d*st*5,0),c.stroke()
|
||||||
|
const ar=shock*.9;c.lineWidth=4.5;for(const d of[-1,1])c.beginPath(),c.moveTo(d*18,-36),c.lineTo(d*(26+4*ar),-22-26*ar),c.stroke()
|
||||||
|
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.ellipse(0,-40,22,28,0,0,T);c.fill();c.stroke()
|
||||||
|
if(shock>.5){
|
||||||
|
c.lineWidth=3;for(const x of[2,17])c.beginPath(),c.arc(x,-48,7.5,0,T),c.fill(),c.stroke()
|
||||||
|
c.fillStyle='#111';for(const x of[2,17])c.beginPath(),c.arc(x+2.5,-46,2.2,0,T),c.fill()
|
||||||
|
c.lineWidth=3;c.beginPath();c.ellipse(11,-30,4,5,0,0,T);c.stroke()
|
||||||
|
c.fillStyle='#74c0fc';c.lineWidth=2.5;const s=(t*3)%1,sy=-60+14*s;c.beginPath();c.moveTo(-17,sy-9);c.quadraticCurveTo(-11,sy,-11,sy+3);c.arc(-17,sy+3,6,0,PI);c.quadraticCurveTo(-23,sy,-17,sy-9);c.fill();c.stroke()
|
||||||
|
}else{
|
||||||
|
c.fillStyle='#111';for(const x of[5,17])c.beginPath(),c.ellipse(x,-44,3,4,0,0,T),c.fill()
|
||||||
|
c.lineWidth=2.5;c.beginPath();c.moveTo(8,-31);c.quadraticCurveTo(12,-29,16,-31);c.stroke()
|
||||||
|
}
|
||||||
|
c.restore()
|
||||||
|
// ! pop over his head
|
||||||
|
const ex=bump(t,.34,.08)
|
||||||
|
if(ex>0){const s=min(1,ex*2.5);c.save();c.translate(hx+16,hy-42);c.scale(s,s);for(const[w,col]of[[16,'#111'],[7,'#fff']])c.lineWidth=w,c.strokeStyle=col,c.beginPath(),c.moveTo(0,-20),c.lineTo(0,2),c.moveTo(0,14),c.lineTo(0,14.1),c.stroke();c.restore()}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
// fed up little guy winds up and hurls his laptop off screen yelling YEET, then a fresh laptop drops right back into his hands
|
||||||
|
import{Path2D}from'@napi-rs/canvas'
|
||||||
|
const{PI,min,max}=Math,T=2*PI
|
||||||
|
const U=[0,.12,.2,.3,.335,.37,.41,.45,.5,.62,.84,.9,.94,.97]
|
||||||
|
export const frames=U.length,delay=[250,80,80,280,50,60,60,60,70,700,70,70,60,300],rim=4
|
||||||
|
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u*u*(3-2*u)),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2),mix=(a,b,u)=>a+(b-a)*u
|
||||||
|
const K='#1b1b1f',B='#4dabf7',BD='#339af0'
|
||||||
|
const F={Y:'M0 0L3 5L6 0M3 5V10',E:'M6 0H0V10H6M0 5H4.5',T:'M0 0H6M3 0V10'}
|
||||||
|
const L=(c,ch,x,y,s,a)=>{c.save();c.translate(x,y);c.rotate(a);c.scale(s*4.8,s*4.8);c.translate(-3,-5);for(const[w,st]of[[5.8,K],[2.4,'#ffd43b']])c.lineWidth=w,c.strokeStyle=st,c.stroke(new Path2D(F[ch]));c.restore()}
|
||||||
|
const lap=(c,x,y,a)=>{c.save();c.translate(x,y);c.rotate(a);c.lineWidth=5;c.strokeStyle=K
|
||||||
|
c.fillStyle='#ced4da';c.beginPath();c.roundRect(-32,-42,64,42,5);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#4dabf7';c.beginPath();c.roundRect(-25,-35,50,28,2);c.fill()
|
||||||
|
c.fillStyle='#d0ebff';c.fillRect(-19,-29,26,4);c.fillRect(-19,-21,16,4)
|
||||||
|
c.fillStyle='#adb5bd';c.beginPath();c.moveTo(-36,0);c.lineTo(36,0);c.lineTo(40,8);c.lineTo(-40,8);c.closePath();c.fill();c.stroke();c.restore()}
|
||||||
|
const arm=(c,x,y,hx,hy)=>{for(const[w,s]of[[22,K],[11,B]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x,y),c.lineTo(hx,hy),c.stroke()
|
||||||
|
c.fillStyle=B;c.strokeStyle=K;c.lineWidth=5;c.beginPath();c.arc(hx,hy,11,0,T);c.fill();c.stroke()}
|
||||||
|
export default(c,_,i)=>{
|
||||||
|
const t=U[i],wu=io((t-.1)/.2),th=io((t-.3)/.06),fo=io((t-.36)/.1),drop=t>.8?io((t-.8)/.14):0,land=t>=.94
|
||||||
|
const lean=-.16*wu+.42*th-.3*io((t-.44)/.18)*(t<.8)
|
||||||
|
const held=t<.335||land,yell=t>=.33&&t<.62,happy=t>=.62&&t<.94
|
||||||
|
// throwing hand path: side, up behind the head, released up front, follow through low
|
||||||
|
let hx=mix(178,92,wu),hy=mix(196,92,wu);if(t>=.3){hx=mix(hx,196,th);hy=mix(hy,108,th);hx=mix(hx,184,fo);hy=mix(hy,214,fo)}
|
||||||
|
if(t>=.8){hx=mix(184,178,drop);hy=mix(214,196,drop)}
|
||||||
|
const behind=wu>.4&&th<.5
|
||||||
|
c.save();c.translate(96,242);c.rotate(lean);c.translate(-96,-242)
|
||||||
|
if(behind)arm(c,136,160,hx,hy),lap(c,hx-4,hy+6,-1.2*wu)
|
||||||
|
c.lineWidth=6;c.strokeStyle=K;c.fillStyle=BD
|
||||||
|
for(const x of[76,116])c.beginPath(),c.roundRect(x-12,206,24,34,11),c.fill(),c.stroke()
|
||||||
|
c.fillStyle=B;c.beginPath();c.ellipse(96,170,56,56,0,0,T);c.fill();c.stroke()
|
||||||
|
c.fillStyle='#fff';c.globalAlpha=.55;c.beginPath();c.ellipse(70,140,10,17,.6,0,T);c.fill();c.globalAlpha=1
|
||||||
|
c.fillStyle=K;c.lineWidth=5
|
||||||
|
if(happy){for(const x of[78,114])c.beginPath(),c.arc(x,166,9,PI*1.1,PI*1.9),c.stroke();c.beginPath();c.arc(96,178,12,.1*PI,.9*PI);c.stroke()
|
||||||
|
c.fillStyle='#ffa8a8';for(const x of[64,128])c.beginPath(),c.ellipse(x,184,8,5,0,0,T),c.fill()}
|
||||||
|
else{for(const x of[78,114])c.beginPath(),c.arc(x,166,6,0,T),c.fill()
|
||||||
|
c.beginPath();c.moveTo(64,146);c.lineTo(90,156);c.moveTo(128,146);c.lineTo(102,156);c.stroke()
|
||||||
|
if(yell){c.beginPath();c.ellipse(97,190,14,13,0,0,T);c.fill();c.fillStyle='#ff8787';c.beginPath();c.ellipse(97,196,8,4,0,0,T);c.fill()}
|
||||||
|
else if(wu>.3&&!th){c.fillStyle='#fff';c.beginPath();c.roundRect(80,180,34,14,4);c.fill();c.stroke();c.beginPath();for(const x of[89,97,105])c.moveTo(x,180),c.lineTo(x,194);c.stroke()}
|
||||||
|
else{c.beginPath();c.moveTo(82,188);c.quadraticCurveTo(96,180,110,188);c.stroke()}}
|
||||||
|
if(land){c.fillStyle='#74c0fc';c.lineWidth=3;c.beginPath();c.moveTo(140,124);c.quadraticCurveTo(149,140,140,145);c.quadraticCurveTo(131,140,140,124);c.fill();c.stroke()}
|
||||||
|
arm(c,48,178,happy?30:yell?24:32,happy?126:yell?150:212)
|
||||||
|
if(!behind){arm(c,140,168,hx,hy);if(held)lap(c,hx+2,hy+4,land?.05:0)}
|
||||||
|
c.restore()
|
||||||
|
if(t>=.335&&t<.5){const u=cl((t-.335)/.12),x=200+130*u,y=96-150*u;c.strokeStyle=K;c.lineWidth=5;c.lineCap='round'
|
||||||
|
if(u<.6)for(const k of[1,2,3])c.globalAlpha=.3*k,c.beginPath(),c.moveTo(x-26*k-14,y+30*k+16),c.lineTo(x-26*k-40,y+30*k+46),c.stroke();c.globalAlpha=1
|
||||||
|
lap(c,x,y,.6+u*5)}
|
||||||
|
if(t>=.8&&!land)lap(c,180,-50+250*drop,.5*(1-drop))
|
||||||
|
;[...'YEET'].forEach((ch,k)=>{const tk=t-.36-k*.035,s=bk(tk/.07)*(1-io((t-.8)/.08)),u=io(tk/.07);if(s>.01)L(c,ch,mix(120,56+k*48,u),mix(110,50+(k%2?-6:6),u),s,(k-1.5)*.14)})
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 189 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 42 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 71 KiB |
|
After Width: | Height: | Size: 80 KiB |
|
After Width: | Height: | Size: 102 KiB |
|
After Width: | Height: | Size: 143 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 81 KiB |
|
After Width: | Height: | Size: 79 KiB |
|
After Width: | Height: | Size: 181 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 84 KiB |
|
After Width: | Height: | Size: 104 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 145 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 63 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 43 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 86 KiB |
|
After Width: | Height: | Size: 87 KiB |
|
After Width: | Height: | Size: 132 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 155 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 134 KiB |
|
After Width: | Height: | Size: 50 KiB |
|
After Width: | Height: | Size: 217 KiB |
|
After Width: | Height: | Size: 133 KiB |
|
After Width: | Height: | Size: 122 KiB |
|
After Width: | Height: | Size: 118 KiB |
|
After Width: | Height: | Size: 193 KiB |
|
After Width: | Height: | Size: 171 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 141 KiB |
|
After Width: | Height: | Size: 138 KiB |
|
After Width: | Height: | Size: 121 KiB |
|
After Width: | Height: | Size: 112 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 134 KiB |