-
-
-
-
-
+
diff --git a/gen/cloud/rain.js b/gen/cloud/rain.js new file mode 100644 index 0000000..a1bb2b5 --- /dev/null +++ b/gen/cloud/rain.js @@ -0,0 +1,17 @@ +// sleepy rain cloud drifting while drops fall out from under it +const{sin,PI}=Math,T=2*PI +export default(c,t)=>{ + for(const[x,o]of[[72,0],[100,.55],[128,.25],[156,.8],[184,.4]]){ + const y=150+((t+o)%1)*120 + c.beginPath();c.moveTo(x,y-14);c.bezierCurveTo(x+3,y-7,x+8,y-3,x+8,y+3);c.arc(x,y+3,8,0,PI);c.bezierCurveTo(x-8,y-3,x-3,y-7,x,y-14) + c.lineWidth=5;c.fill();c.stroke() + } + const y=sin(t*T)*3,parts=[[78,118+y,36],[124,92+y,48],[176,112+y,38]],base=()=>c.roundRect(44,112+y,168,52,26) + c.lineWidth=14;for(const[x,yy,r]of parts)c.beginPath(),c.arc(x,yy,r,0,T),c.stroke() + c.beginPath();base();c.stroke() + for(const[x,yy,r]of parts)c.beginPath(),c.arc(x,yy,r,0,T),c.fill() + c.beginPath();base();c.fill() + c.lineWidth=6 + for(const x of[104,152])c.beginPath(),c.arc(x,126+y,9,PI*.15,PI*.85),c.stroke() + c.beginPath();c.arc(128,154+y,8,PI*1.2,PI*1.8);c.stroke() +} diff --git a/gen/coffee/steam.js b/gen/coffee/steam.js new file mode 100644 index 0000000..ce06707 --- /dev/null +++ b/gen/coffee/steam.js @@ -0,0 +1,22 @@ +// happy coffee mug rocking a little while steam curls up out of it +const{sin,PI}=Math,T=2*PI +export const delay=90 +export default(c,t)=>{ + c.save();c.translate(119,214);c.rotate(.04*sin(t*T));c.translate(-119,-214) + for(const[w,s]of[[27,'#111'],[13,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(172,160,26,-PI/2,PI/2),c.stroke() + c.lineWidth=7;c.strokeStyle='#111' + c.beginPath();c.moveTo(66,120);c.lineTo(66,192);c.quadraticCurveTo(66,214,88,214);c.lineTo(150,214);c.quadraticCurveTo(172,214,172,192);c.lineTo(172,120) + c.ellipse(119,120,53,12,0,0,PI,true);c.fill();c.stroke() + c.beginPath();c.ellipse(119,120,53,12,0,0,T);c.fill();c.stroke() + c.fillStyle='#111';c.beginPath();c.ellipse(119,121,42,7,0,0,T);c.fill() + c.lineWidth=6 + for(const x of[100,138])c.beginPath(),c.arc(x,166,8,PI*1.15,PI*1.85),c.stroke() + c.beginPath();c.arc(119,174,10,PI*.2,PI*.8);c.stroke() + c.restore() + for(const[x0,top,ph]of[[93,46,0],[119,30,.5],[145,46,1]]) + for(const[w,s]of[[13,'#111'],[6,'#fff']]){ + c.lineWidth=w;c.strokeStyle=s;c.beginPath() + for(let y=100;y>=top;y-=2)c.lineTo(x0+(2+5*(100-y)/70)*sin((100-y)/40*T-t*T+ph),y) + c.stroke() + } +} diff --git a/gen/ghost/float.js b/gen/ghost/float.js new file mode 100644 index 0000000..87cf08d --- /dev/null +++ b/gen/ghost/float.js @@ -0,0 +1,18 @@ +// ghost bobbing in place, hem rippling, little arms flapping, blinks once per loop +const{sin,PI}=Math,T=2*PI +export default(c,t,i)=>{ + const y=sin(t*T)*8,L=66,R=190,hem=x=>196+y+7*sin((x-L)/(R-L)*3*T-t*T) + for(const s of[-1,1]){ + c.beginPath();c.ellipse(128+s*68,150+y,20,10,s*(.5+.3*sin(t*T*2)),0,T);c.fill();c.stroke() + } + c.beginPath();c.moveTo(L,hem(L));c.arc(128,104+y,62,PI,0) + for(let x=R;x>=L;x-=2)c.lineTo(x,hem(x)) + c.closePath();c.fill();c.stroke() + c.fillStyle='#111' + for(const x of[106,150]){ + c.beginPath() + if(i==11||i==12)c.moveTo(x-7,108+y),c.lineTo(x+7,108+y),c.stroke() + else c.ellipse(x,108+y,6.5,10,0,0,T),c.fill(),c.fillStyle='#fff',c.beginPath(),c.arc(x-2,104+y,2.5,0,T),c.fill(),c.fillStyle='#111' + } + c.beginPath();c.ellipse(128,138+y,6,8,0,0,T);c.fill() +} diff --git a/gen/heart/beat.js b/gen/heart/beat.js new file mode 100644 index 0000000..82b034a --- /dev/null +++ b/gen/heart/beat.js @@ -0,0 +1,19 @@ +// heart thumping with a double beat, pop lines burst out on the big one +const{exp,cos,sin,PI}=Math +const p=(t,m)=>exp(-((((t-m+1.5)%1-.5)/.06)**2)) +export const delay=60 +export default(c,t)=>{ + const s=1+.14*p(t,.1)+.07*p(t,.32),k=p(t,.1) + c.translate(128,140);c.scale(s,s);c.lineWidth/=s + c.beginPath();c.moveTo(0,70) + c.bezierCurveTo(-30,45,-92,10,-92,-30);c.bezierCurveTo(-92,-62,-66,-82,-44,-82);c.bezierCurveTo(-22,-82,-6,-68,0,-50) + c.bezierCurveTo(6,-68,22,-82,44,-82);c.bezierCurveTo(66,-82,92,-62,92,-30);c.bezierCurveTo(92,10,30,45,0,70) + c.closePath();c.fill();c.stroke() + c.beginPath();c.arc(-46,-34,24,PI*1.1,PI*1.45);c.stroke() + if(k<.15)return + for(const[x,a]of[[-46,-140],[-46,-110],[-46,-80],[46,-40],[46,-70],[46,-100]]) + for(const[w,s2]of[[12,'#111'],[5,'#fff']]){ + const r=a*PI/180;c.lineWidth=w/s;c.strokeStyle=s2;c.beginPath() + c.moveTo(x+cos(r)*56,-38+sin(r)*56);c.lineTo(x+cos(r)*(56+16*k),-38+sin(r)*(56+16*k));c.stroke() + } +} diff --git a/index.html b/index.html index c2c2772..5151ab7 100644 --- a/index.html +++ b/index.html @@ -13,7 +13,10 @@ h1{font-weight:400;font-size:clamp(22px,5vw,44px);line-height:1.2;margin:8px aut p{font-size:clamp(16px,3vw,22px);margin-bottom:16px} iframe{border:0;border-radius:6px;margin-bottom:28px} main{display:grid;grid-template-columns:repeat(auto-fill,minmax(150px,1fr));gap:16px;max-width:1400px;margin:auto} -a{display:flex;align-items:center;justify-content:center;aspect-ratio:1} +figure>a{display:flex;align-items:center;justify-content:center;aspect-ratio:1} +figcaption{font-size:14px;margin-top:4px} +figcaption a{color:#888;text-decoration:none;margin:0 4px} +figcaption a:hover{color:#000;text-decoration:underline} img{width:100%;height:100%;object-fit:contain} @media(max-width:480px){main{grid-template-columns:repeat(3,1fr);gap:10px}} @@ -23,12 +26,7 @@ img{width:100%;height:100%;object-fit:contain}
feel free to hot link them
-
-
-
-
-
+