mirror of
https://github.com/direct-img/vibegif.direct-img.link.git
synced 2026-10-29 11:44:51 +00:00
Add code-generated animations and build the gallery from public/
Each animation is its own file in gen/<subject>/<action>.js; npm run gen renders the missing ones to public/ as webp + gif. The homepage grid is now generated at build time by a small Vite plugin. First four: ghost/float, heart/beat, cloud/rain, coffee/steam. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -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()
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user