diff --git a/gen/ui/429/gauge.js b/gen/ui/429/gauge.js new file mode 100644 index 0000000..e1f82ab --- /dev/null +++ b/gen/ui/429/gauge.js @@ -0,0 +1,33 @@ +// a stressed speed gauge's needle climbs and jitters in the hatched red zone while the dial trembles, steams and flashes alert lines, then drops back and climbs again +const{sin,cos,PI,min,max}=Math,T=2*PI +export const frames=24,delay=70 +const ease=u=>(u=min(1,max(0,u)),u<.5?2*u*u:1-2*(1-u)**2) +const ln=(c,w,f)=>{for(const[l,s]of[[w,'#111'],[w-7,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'} +const X=128,Y=146,A=PI*5/6,SW=PI*4/3,ang=v=>A+SW*v +export default(c,t,i)=>{ + const hot=t>=.4&&t<.72,v=t<.4?.06+.82*(t/.4)**2:hot?.9+(i%2?.05:-.03):.06+.84*(1-ease((t-.72)/.14)) + if(hot){ + for(const d of[-1,1])for(const a of[-.45,0,.45])ln(c,11,()=>{const b=-PI/2+d*(1.2+a*.4),r=i%2?5:0;c.moveTo(X+cos(b)*(104+r),Y+sin(b)*(104+r));c.lineTo(X+cos(b)*(120+r),Y+sin(b)*(120+r))}) + c.translate(i%2?3:-3,i%3-1) + } + c.lineWidth=7;c.beginPath();c.arc(X,Y,92,0,T);c.fill();c.stroke() + c.lineWidth=5;c.beginPath();c.arc(X,Y,80,0,T);c.stroke() + c.save();c.beginPath();c.arc(X,Y,74,ang(.72),ang(1));c.arc(X,Y,54,ang(1),ang(.72),true);c.closePath();c.clip() + c.lineWidth=5;for(let x=40;x<240;x+=11)c.beginPath(),c.moveTo(x,20),c.lineTo(x-60,120),c.stroke() + c.restore();c.lineWidth=5;c.beginPath();c.arc(X,Y,74,ang(.72),ang(1));c.arc(X,Y,54,ang(1),ang(.72),true);c.closePath();c.stroke() + for(let k=0;k<=8;k++){const a=ang(k/8),r=k%2?66:58;c.lineWidth=k%2?4:6;c.beginPath();c.moveTo(X+cos(a)*r,Y+sin(a)*r);c.lineTo(X+cos(a)*74,Y+sin(a)*74);c.stroke()} + const a=ang(v) + c.fillStyle='#111';c.beginPath();c.moveTo(X+cos(a)*68,Y+sin(a)*68);c.lineTo(X+cos(a+PI/2)*8,Y+sin(a+PI/2)*8);c.lineTo(X-cos(a)*14,Y-sin(a)*14);c.lineTo(X+cos(a-PI/2)*8,Y+sin(a-PI/2)*8);c.closePath();c.fill() + c.fillStyle='#fff';c.lineWidth=6;c.beginPath();c.arc(X,Y,12,0,T);c.fill();c.stroke() + c.fillStyle='#111';c.lineWidth=5 + if(hot){ + for(const d of[-1,1])c.beginPath(),c.moveTo(X+d*24,180),c.lineTo(X+d*14,186),c.lineTo(X+d*24,192),c.stroke() + c.beginPath();for(let k=0;k<=6;k++)c.lineTo(X-15+k*5,206+(k%2?-3:3));c.stroke() + c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.moveTo(X+40,170);c.bezierCurveTo(X+34,182,X+36,190,X+42,190);c.bezierCurveTo(X+48,190,X+50,182,X+40,170);c.fill();c.stroke() + }else{ + const w=v>.5?8:6 + for(const d of[-1,1])c.beginPath(),c.arc(X+d*18,186,w*.75,0,T),c.fill() + c.beginPath();v>.5?c.ellipse(X,204,6,5,0,0,T):c.arc(X,200,8,PI*.15,PI*.85);v>.5?c.fill():c.stroke() + } + if(hot)for(const d of[-1,1])for(const o of[0,.5]){const p=((t-.4)/.32*2+o)%1;c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.arc(X+d*(56+14*p),Y-74-36*p,6+9*p,0,T);c.fill();c.stroke()} +} diff --git a/gen/ui/calendar/empty.js b/gen/ui/calendar/empty.js deleted file mode 100644 index fb9ad9e..0000000 --- a/gen/ui/calendar/empty.js +++ /dev/null @@ -1,23 +0,0 @@ -// tear-off calendar pad, the top page flips up over the binding and away, but every page underneath is blank too -const{sin,cos,PI,min,max}=Math -export const frames=32,delay=55 -const ease=u=>(u=min(1,max(0,u)),u<.5?2*u*u:1-2*(1-u)**2) -const X=128,Y=102,W=160,H=124 -const flip=(c,a)=>{ - const k=cos(a),y=Y+H*k*(k>0?1:.62),w=W/2*(1+.2*sin(a)),y0=k>0?Y-20:Y - c.fillStyle=k>0?'#fff':'#ddd' - c.beginPath();c.moveTo(X-W/2,y0);c.lineTo(X-w,y);c.lineTo(X+w,y);c.lineTo(X+W/2,y0);c.closePath();c.fill();c.stroke() - c.fillStyle='#fff' -} -export default(c,t)=>{ - const a=1.5*PI*ease((t*2%1)/.78) - if(a>PI)flip(c,a) - c.beginPath();c.rect(X-W/2+5,Y-10,W-10,H+20);c.fill();c.stroke() - c.beginPath();c.rect(X-W/2,Y-20,W,H+20);c.fill();c.stroke() - if(a=PI/2&&a<=PI)flip(c,a) -} diff --git a/gen/ui/chat/crickets.js b/gen/ui/chat/crickets.js deleted file mode 100644 index 31fc028..0000000 --- a/gen/ui/chat/crickets.js +++ /dev/null @@ -1,26 +0,0 @@ -// an empty speech bubble hangs in awkward silence while a little cricket beside it rubs its wings and chirps -const{sin,cos,PI}=Math,T=2*PI -export const frames=20,delay=70 -const ln=(c,w,f)=>{for(const[l,s]of[[w,'#111'],[w-7,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'} -export default(c,t,i)=>{ - const ch=t*2%1<.4,j=ch?(i%2?1:-1):0,b=3*sin(t*T) - c.save();c.translate(92,68+b);c.rotate(.03*sin(t*T)) - c.beginPath();c.moveTo(-36,-50);c.arcTo(76,-50,76,50,36);c.arcTo(76,50,-76,50,36);c.lineTo(-12,50);c.lineTo(-50,86);c.lineTo(-38,50);c.arcTo(-76,50,-76,-50,36);c.arcTo(-76,-50,76,-50,36);c.closePath();c.fill();c.stroke() - c.restore() - c.save();c.translate(142,198-(ch&&i%2?2:0));c.scale(1.15,1.15) - if(ch)for(const a of[-1.5,-1.05,-.6])ln(c,10,()=>{const r=j>0?4:0;c.moveTo(46+cos(a)*(42+r),-32+sin(a)*(42+r));c.lineTo(46+cos(a)*(56+r),-32+sin(a)*(56+r))}) - for(const o of[0,1])ln(c,9,()=>{c.moveTo(-36-o*8,-22);c.quadraticCurveTo(-30+o*14,-80,10+o*22+5*sin(t*T*2+o*2),-92+o*12)}) - for(const[x,y,fx,fy]of[[-22,10,-36,30],[2,14,-6,30]])ln(c,11,()=>{c.moveTo(x,y);c.lineTo(fx,fy);c.lineTo(fx-10,fy)}) - c.beginPath();c.ellipse(20,0,46,24,0,0,T);c.fill();c.stroke() - c.save();c.translate(-12,-16);c.rotate(ch?-.32+.1*j:-.06) - c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(40,-24,78,6);c.quadraticCurveTo(40,4,0,0);c.fill();c.stroke() - c.lineWidth=4;c.beginPath();c.moveTo(14,-2);c.quadraticCurveTo(40,-10,62,2);c.stroke() - c.restore() - ln(c,11,()=>{c.moveTo(58,-30);c.lineTo(74,26);c.lineTo(84,26)}) - c.save();c.translate(40,-10);c.rotate(-.55);c.beginPath();c.ellipse(0,0,32,13,0,0,T);c.fill();c.stroke();c.restore() - c.beginPath();c.arc(-36,-4,25,0,T);c.fill();c.stroke() - c.fillStyle='#111';c.beginPath();c.arc(-44,-10,7,0,T);c.fill() - c.fillStyle='#fff';c.beginPath();c.arc(-46,-12,2.5,0,T);c.fill() - c.lineWidth=4;c.beginPath();c.arc(-46,4,7,.2*PI,.8*PI);c.stroke() - c.restore() -} diff --git a/gen/ui/confirmed/handshake.js b/gen/ui/confirmed/handshake.js deleted file mode 100644 index 8cfd7e8..0000000 --- a/gen/ui/confirmed/handshake.js +++ /dev/null @@ -1,21 +0,0 @@ -// two hands clasped in a handshake, pumping up and down, with little shake lines above and below -const{sin,cos,PI,atan2,hypot}=Math,T=2*PI -export const frames=16,delay=70 -export default(c,t)=>{ - const D=(f,a=12,b=5)=>{for(const[w,s]of[[a,'#111'],[b,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'} - const v=sin(2*T*t),cx=128,cy=108+14*v,S=1.35,w=7/S - for(const s of[-1,1])if(s*cos(2*T*t)<-.3)for(const k of[0,1])D(()=>{const y=cy+s*(s<0?56:62)+s*k*14;c.moveTo(cx-24+k*6,y+s*6);c.quadraticCurveTo(cx,y-s*4,cx+24-k*6,y+s*6)},11,4) - for(const d of[-1,1]){ - const wx=cx+d*66,wy=cy+12,ex=128+d*88,ey=224,r=atan2(ey-wy,ex-wx),l=hypot(ex-wx,ey-wy) - c.save();c.translate(wx,wy);c.rotate(r) - c.fillStyle=d<0?'#777':'#fff';c.beginPath();c.roundRect(6,-25,l,50,14);c.fill();c.stroke() - c.fillStyle='#fff';c.beginPath();c.roundRect(-6,-30,18,60,7);c.fill();c.stroke() - c.restore() - } - c.save();c.translate(cx,cy);c.rotate(.05*v);c.scale(S,S);c.lineWidth=w - c.beginPath();c.roundRect(-14,-22,62,46,20);c.fill();c.stroke() - c.beginPath();c.roundRect(-52,-24,52,46,20);c.fill();c.stroke() - for(const[y,l]of[[16,22],[6,32],[-4,36],[-14,32]])c.beginPath(),c.roundRect(-10,y-6,l,12,6),c.fill(),c.stroke() - c.beginPath();c.roundRect(-40,-31,48,15,7.5);c.fill();c.stroke();c.lineWidth=w*.7;c.beginPath();c.moveTo(-31,-27);c.lineTo(-31,-20);c.stroke() - c.restore() -} diff --git a/gen/ui/liked/heart.js b/gen/ui/liked/heart.js new file mode 100644 index 0000000..8c47c33 --- /dev/null +++ b/gen/ui/liked/heart.js @@ -0,0 +1,27 @@ +// a heart outline gets tapped, squashes, then pops big and fills in while a ring of tiny hearts and dots bursts out, settles, and drains back to an outline +const{sin,cos,PI,min,max,exp}=Math,T=2*PI +export const frames=24,delay=60 +const ease=u=>(u=min(1,max(0,u)),u<.5?2*u*u:1-2*(1-u)**2) +const hp=(c,s)=>{c.beginPath();c.moveTo(0,-26*s);c.bezierCurveTo(-14*s,-56*s,-62*s,-54*s,-62*s,-16*s);c.bezierCurveTo(-62*s,14*s,-26*s,34*s,0,56*s);c.bezierCurveTo(26*s,34*s,62*s,14*s,62*s,-16*s);c.bezierCurveTo(62*s,-54*s,14*s,-56*s,0,-26*s);c.closePath()} +export default(c,t)=>{ + const u=(t-.2)/.34,k=t>.1&&t<.2?sin(PI*(t-.1)/.2):0,full=t>=.2&&t<.96,lv=-58+116*ease((t-.8)/.16) + const s=t<.2?1:u<.2?.88+.42*(u/.2)**.7:1+.3*exp(-6*(u-.2))*cos((u-.2)*T*1.4) + c.translate(128,130);c.scale(.86,.86) + if(u>0&&u<1){ + const r=84+38*(1-(1-u)**3),z=1-u*u + for(let j=0;j<12;j++){ + const a=j*T/12-PI/2,x=cos(a)*(j%2?r*.85:r),y=sin(a)*(j%2?r*.85:r) + c.save();c.translate(x,y);c.lineWidth=5 + if(j%2)c.beginPath(),c.arc(0,0,9*z+2,0,T),c.fill(),c.stroke() + else c.rotate(a+PI/2),hp(c,.3*z+.06),c.fill(),c.stroke() + c.restore() + } + } + if(t>.08&&t<.24){const v=(t-.08)/.16;for(const[w,st]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.arc(0,0,8+30*v,0,T),c.stroke()} + c.scale(s*(1+.12*k),s*(1-.16*k));c.translate(0,10*k) + if(full){ + c.save();hp(c,1);c.clip();c.fillStyle='#555';c.fillRect(-70,max(-70,lv),140,140);c.restore() + if(lv<-20){c.fillStyle='#fff';c.strokeStyle='#fff';c.lineWidth=9;c.beginPath();c.arc(-30,-18,20,PI*1.05,PI*1.5);c.stroke();c.beginPath();c.arc(-44,8,5,0,T);c.fill()} + } + for(const[w,st]of[[22,'#111'],[9,'#fff']])c.lineWidth=w,c.strokeStyle=st,hp(c,1),c.stroke() +} diff --git a/gen/ui/tumbleweed/roll.js b/gen/ui/tumbleweed/roll.js new file mode 100644 index 0000000..f00590b --- /dev/null +++ b/gen/ui/tumbleweed/roll.js @@ -0,0 +1,31 @@ +// a big scribbly tumbleweed bounces and spins along empty desert ground in the wind, puffing dust on each landing while pebbles and sand dashes scroll past +const{sin,cos,PI,min}=Math,T=2*PI +export const frames=16,delay=75 +let sd=53;const rn=()=>(sd=sd*16807%2147483647)/2147483647 +const R=60,S=T*R,W=[] +for(let k=0;k<7;k++){ + const rx=R*(.5+rn()*.38),ry=rx*(.4+rn()*.45),a=rn()*T,d=rn()*(R*.96-rx),r0=rn()*T,o=rn()*T,n=.85+rn()*.3,p=[] + for(let j=0;j<=56;j++){const b=o+j/56*T*n,w=1+.07*sin(3*b+k)+.05*sin(13*b+k*3),x=cos(b)*rx*w,y=sin(b)*ry*w;p.push([cos(a)*d+x*cos(r0)-y*sin(r0),sin(a)*d+x*sin(r0)+y*cos(r0)])} + W.push(p) +} +for(let k=0;k<2;k++){const p=[],o=rn()*T;for(let j=0;j<=60;j++){const b=o+j/52*T,r=R*(.9+.06*sin(b*5+k*2)+.03*sin(b*11+k));p.push([cos(b)*r,sin(b)*r])}W.push(p)} +const P=(r,b)=>[cos(b)*R*r,sin(b)*R*r] +for(let k=0;k<3;k++){const b=rn()*T,p=[];for(let j=0;j<=20;j++){const v=j/20*2-1;p.push([cos(b)*v*R*.82-sin(b)*R*.2*sin(v*PI*1.5+k),sin(b)*v*R*.82+cos(b)*R*.2*sin(v*PI*1.5+k)])}W.push(p)} +for(let k=0;k<12;k++){const b=k*T/12+rn()*.3,e=(rn()-.5)*.4;W.push([P(.86,b),P(1.13,b+e)],[P(1.01,b+e*.6),P(1.1,b+e*.6+.17)])} +const ln=(c,w,f)=>{for(const[l,s]of[[w,'#111'],[w-7,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'} +const scr=(x0,t)=>((x0-S*t)%S+S)%S-48 +export default(c,t)=>{ + const q=t*2%1,G=226,e=min(q,1-q),sy=e<.08?.9+.1*e/.08:1,x=124+10*sin(T*t),y=G-R-42*4*q*(1-q) + c.save();c.translate(226,G) + for(const[w,s]of[[13,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(-8,-16),c.lineTo(-15,-16),c.lineTo(-15,-27),c.moveTo(8,-22),c.lineTo(15,-22),c.lineTo(15,-33),c.stroke() + c.lineWidth=5;c.strokeStyle='#111';c.beginPath();c.roundRect(-7,-38,14,40,7);c.fill();c.stroke() + c.restore() + ln(c,11,()=>{c.moveTo(14,G);c.lineTo(242,G)}) + for(const x0 of[30,150,262])ln(c,10,()=>{const u=scr(x0,t);c.moveTo(u,G+14);c.lineTo(u+18,G+14)}) + for(const[x0,r]of[[96,14],[214,10],[318,12]]){const u=scr(x0,t);c.lineWidth=4;c.beginPath();c.ellipse(u,G,r,r*.75,0,PI,0);c.closePath();c.fill();c.stroke()} + for(let k=0;k<3;k++){const p=(t*3+k/3)%1,yy=y-38+k*30,x1=x-R-14-26*p,L=30*(1-p)+8;if(x1-L>8)ln(c,11,()=>{c.moveTo(x1,yy);c.lineTo(x1-L,yy)})} + if(q<.45)for(const d of[-1,1])for(const[o,s0]of[[26,11],[46,7]]){const p=q/.45,u=x+d*(o+14*p)-60*p;c.lineWidth=5;c.beginPath();c.arc(u,G-6-12*p,s0*(1-p)+2,0,T);c.fill();c.stroke()} + c.save();c.translate(x,y+R);c.scale(2-sy,sy);c.translate(0,-R);c.rotate(T*t) + for(const[w,s]of[[11,'#fff'],[4.5,'#111']]){c.lineWidth=w;c.strokeStyle=s;for(const p of W){c.beginPath();for(const[a,b]of p)c.lineTo(a,b);c.stroke()}} + c.restore() +} diff --git a/public/429/gauge.gif b/public/429/gauge.gif new file mode 100644 index 0000000..67230ba Binary files /dev/null and b/public/429/gauge.gif differ diff --git a/public/429/gauge.webp b/public/429/gauge.webp new file mode 100644 index 0000000..78dfd95 Binary files /dev/null and b/public/429/gauge.webp differ diff --git a/public/calendar/empty.gif b/public/calendar/empty.gif deleted file mode 100644 index dbc4d48..0000000 Binary files a/public/calendar/empty.gif and /dev/null differ diff --git a/public/calendar/empty.webp b/public/calendar/empty.webp deleted file mode 100644 index 05112cc..0000000 Binary files a/public/calendar/empty.webp and /dev/null differ diff --git a/public/chat/crickets.gif b/public/chat/crickets.gif deleted file mode 100644 index cb783ce..0000000 Binary files a/public/chat/crickets.gif and /dev/null differ diff --git a/public/chat/crickets.webp b/public/chat/crickets.webp deleted file mode 100644 index 6c9c61f..0000000 Binary files a/public/chat/crickets.webp and /dev/null differ diff --git a/public/confirmed/handshake.gif b/public/confirmed/handshake.gif deleted file mode 100644 index 97cf759..0000000 Binary files a/public/confirmed/handshake.gif and /dev/null differ diff --git a/public/confirmed/handshake.webp b/public/confirmed/handshake.webp deleted file mode 100644 index 5cce597..0000000 Binary files a/public/confirmed/handshake.webp and /dev/null differ diff --git a/public/liked/heart.gif b/public/liked/heart.gif new file mode 100644 index 0000000..27cc6ca Binary files /dev/null and b/public/liked/heart.gif differ diff --git a/public/liked/heart.webp b/public/liked/heart.webp new file mode 100644 index 0000000..dfebcea Binary files /dev/null and b/public/liked/heart.webp differ diff --git a/public/tumbleweed/roll.gif b/public/tumbleweed/roll.gif new file mode 100644 index 0000000..a94d32e Binary files /dev/null and b/public/tumbleweed/roll.gif differ diff --git a/public/tumbleweed/roll.webp b/public/tumbleweed/roll.webp new file mode 100644 index 0000000..a51c9f6 Binary files /dev/null and b/public/tumbleweed/roll.webp differ