diff --git a/gen/balloon/float.js b/gen/balloon/float.js new file mode 100644 index 0000000..898262f --- /dev/null +++ b/gen/balloon/float.js @@ -0,0 +1,26 @@ +// two balloons tied together bobbing and swaying out of step, strings waving +const{sin,cos,PI}=Math,T=2*PI +export const frames=20,delay=80 +const balloon=(c,x,y,r,a)=>{ + c.save();c.translate(x,y);c.rotate(a) + c.beginPath();c.moveTo(0,-r*1.15);c.bezierCurveTo(r*1.12,-r*1.15,r*1.05,r*.6,0,r*1.05);c.bezierCurveTo(-r*1.05,r*.6,-r*1.12,-r*1.15,0,-r*1.15);c.fill();c.stroke() + c.beginPath();c.moveTo(0,r*1.05);c.lineTo(-7,r*1.05+11);c.lineTo(7,r*1.05+11);c.closePath();c.fill();c.stroke() + c.lineWidth=5;c.beginPath();c.arc(0,-r*.1,r*.75,PI*1.12,PI*1.38);c.stroke();c.lineWidth=7 + c.restore() +} +export default(c,t)=>{ + const B=[[170,96,40,.6],[100,84,52,0]].map(([x,y,r,o])=>{const a=.12*sin(t*T+o*5),bx=x+6*sin(t*T+o*5),by=y+6*sin(2*T*t+o*3);return[bx,by,r,a]}) + for(const[bx,by,r,a]of B){ + const kx=bx-sin(a)*(r*1.05+11),ky=by+cos(a)*(r*1.05+11) + for(const[w,s]of[[8,'#111'],[3,'#fff']]){ + c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.moveTo(kx,ky) + for(let u=0;u<=1;u+=.05)c.lineTo(kx+(132-kx)*u+6*sin(u*7-t*T*2)*(1-u),ky+(240-ky)*u) + c.stroke() + } + } + c.lineWidth=7;c.strokeStyle='#111' + for(const b of B)balloon(c,...b) + const[bx,by]=B[1] + c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(bx+d*15,by-4,5,0,T),c.fill() + c.lineWidth=5;c.beginPath();c.arc(bx,by+8,10,.15*PI,.85*PI);c.stroke() +} diff --git a/gen/bell/ring.js b/gen/bell/ring.js new file mode 100644 index 0000000..02434d2 --- /dev/null +++ b/gen/bell/ring.js @@ -0,0 +1,17 @@ +// bell swinging back and forth, clapper lagging behind, ring lines on each swing +const{sin,cos,PI,abs}=Math,T=2*PI +export const frames=20,delay=60 +export default(c,t)=>{ + const a=.38*sin(2*T*t),ca=-.5*sin(2*T*t-.9) + if(abs(a)>.3){ + const d=a>0?-1:1 + for(const r of[96,118])for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(128,120,r,d>0?-.35:PI-.35,d>0?.35:PI+.35),c.stroke() + } + c.lineWidth=7;c.strokeStyle='#111' + c.translate(128,48);c.rotate(a) + c.save();c.rotate(ca);c.beginPath();c.moveTo(0,40);c.lineTo(0,140);c.lineWidth=6;c.stroke();c.lineWidth=7;c.beginPath();c.arc(0,150,13,0,T);c.fill();c.stroke();c.restore() + c.beginPath();c.arc(0,4,10,0,T);c.fill();c.stroke() + c.beginPath();c.moveTo(-46,128);c.bezierCurveTo(-46,86,-42,16,0,14);c.bezierCurveTo(42,16,46,86,46,128);c.closePath();c.fill();c.stroke() + c.beginPath();c.roundRect(-60,122,120,20,10);c.fill();c.stroke() + c.lineWidth=5;c.beginPath();c.moveTo(-28,40);c.quadraticCurveTo(-34,70,-34,100);c.stroke() +} diff --git a/gen/bulb/idea.js b/gen/bulb/idea.js new file mode 100644 index 0000000..ebe24d2 --- /dev/null +++ b/gen/bulb/idea.js @@ -0,0 +1,24 @@ +// sleepy light bulb flickers on, wakes up with a grin and shines, then dozes off again +const{sin,cos,PI}=Math,T=2*PI +export const frames=24,delay=70 +export default(c,t,i)=>{ + const on=t>=.36&&t<.86||t>=.25&&t<.36&&i%2==1 + if(on)for(let k=0;k<7;k++){ + const a=PI+k*PI/6,r1=74,r2=96+6*sin(2*T*t*2+k) + for(const[w,s]of[[13,'#111'],[5,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(128+cos(a)*r1,100+sin(a)*r1),c.lineTo(128+cos(a)*r2,100+sin(a)*r2),c.stroke() + } + c.lineWidth=7;c.strokeStyle='#111' + c.beginPath();c.arc(128,100,58,.7*PI,.3*PI);c.lineTo(150,170);c.lineTo(106,170);c.closePath();c.fill();c.stroke() + for(const[x,y,w,h]of[[102,168,52,13],[105,181,46,13],[112,194,32,12]])c.beginPath(),c.roundRect(x,y,w,h,5),c.fill(),c.stroke() + c.beginPath();c.arc(128,208,7,0,PI);c.fill();c.stroke() + c.lineWidth=5 + if(on){ + c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*20,100,6,0,T),c.fill() + c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*20-2,97,2.2,0,T),c.fill() + c.beginPath();c.arc(128,112,16,.15*PI,.85*PI);c.stroke() + c.lineWidth=4;c.beginPath();c.arc(128,100,44,PI*1.15,PI*1.4);c.stroke() + }else{ + for(const d of[-1,1])c.beginPath(),c.arc(128+d*20,98,7,.15*PI,.85*PI),c.stroke() + c.beginPath();c.moveTo(122,122);c.lineTo(134,122);c.stroke() + } +} diff --git a/gen/check/done.js b/gen/check/done.js new file mode 100644 index 0000000..b006f17 --- /dev/null +++ b/gen/check/done.js @@ -0,0 +1,17 @@ +// badge pops in, a check mark draws itself, a burst of lines goes off, then it shrinks away +const{sin,cos,PI,min,max,hypot}=Math,T=2*PI +export const frames=24,delay=60 +const back=u=>{const s=2;return 1+(s+1)*(u-1)**3+s*(u-1)**2} +const P=[[90,132],[118,160],[168,102]],L=hypot(28,28)+hypot(50,58) +export default(c,t)=>{ + const s=t<.15?back(t/.15):t>.85?1-((t-.85)/.15)**2:1,p=min(1,max(0,(t-.15)/.28)),b=(t-.45)/.25 + if(b>0&&b<1)for(let k=0;k<8;k++){ + const a=k*T/8+PI/8,r1=82+30*b,r2=r1+20*(1-b) + for(const[w,st]of[[12,'#111'],[5,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(128+cos(a)*r1,128+sin(a)*r1),c.lineTo(128+cos(a)*r2,128+sin(a)*r2),c.stroke() + } + c.strokeStyle='#111';c.lineWidth=7 + if(s<=.01)return + c.translate(128,128);c.scale(s,s);c.translate(-128,-128);c.lineWidth=7/s + c.beginPath();c.arc(128,128,74,0,T);c.fill();c.stroke() + if(p>0){c.lineWidth=20;c.setLineDash([L*p,999]);c.beginPath();for(const[x,y]of P)c.lineTo(x,y);c.stroke();c.setLineDash([])} +} diff --git a/gen/hourglass/flip.js b/gen/hourglass/flip.js new file mode 100644 index 0000000..0023ca9 --- /dev/null +++ b/gen/hourglass/flip.js @@ -0,0 +1,25 @@ +// sand runs from the top bulb to the bottom, then the hourglass flips over and it starts again +const{PI,min}=Math,T=2*PI +export const frames=24,delay=90 +const glass=c=>{ + c.beginPath();c.moveTo(86,54);c.bezierCurveTo(86,100,120,110,122,128);c.bezierCurveTo(120,146,86,156,86,202) + c.lineTo(170,202);c.bezierCurveTo(170,156,136,146,134,128);c.bezierCurveTo(136,110,170,100,170,54);c.closePath() +} +export default(c,t)=>{ + const p=min(1,t/.72),f=t>.75?(t-.75)/.25:0,e=f<.5?2*f*f:1-2*(1-f)**2 + c.translate(128,128);c.rotate(e*PI);c.translate(-128,-128) + glass(c);c.fill() + c.save();glass(c);c.clip();c.fillStyle='#111' + if(f>0)c.fillRect(80,152-24*e,96,52+4*e) + else{ + const top=72+p*56,lv=204-52*p,m=22*Math.sin(PI*p) + c.fillRect(80,top,96,128-top) + if(p>0){c.beginPath();c.moveTo(80,204);c.lineTo(80,lv+m*.4);c.quadraticCurveTo(128,lv-m,176,lv+m*.4);c.lineTo(176,204);c.fill()} + if(p<1)c.fillRect(126,126,4,80) + } + c.restore() + glass(c);c.stroke() + for(const x of[74,182])for(const[w,s]of[[14,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x,50),c.lineTo(x,206),c.stroke() + c.lineWidth=7;c.strokeStyle='#111' + for(const y of[36,204])c.beginPath(),c.roundRect(62,y,132,16,7),c.fill(),c.stroke() +} diff --git a/gen/mail/open.js b/gen/mail/open.js new file mode 100644 index 0000000..63d2834 --- /dev/null +++ b/gen/mail/open.js @@ -0,0 +1,16 @@ +// envelope flap opens, a letter with a beating heart slides out, then tucks back in and the flap closes +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) +export default(c,t)=>{ + const fy=1-2*ease(t/.18)+2*ease((t-.82)/.18),ly=118-78*ease((t-.18)/.25)+78*ease((t-.62)/.2),hb=1+.15*sin(2*T*t*3) + const flap=()=>{c.beginPath();c.moveTo(48,110);c.lineTo(128,110+64*fy);c.lineTo(208,110);c.closePath();c.fill();c.stroke()} + c.beginPath();c.roundRect(48,108,160,108,10);c.fill();c.stroke() + if(fy<0)flap() + c.beginPath();c.rect(68,ly,120,96);c.fill();c.stroke() + c.lineWidth=4;for(const y of[64,76])c.beginPath(),c.moveTo(92,ly+y),c.lineTo(164,ly+y),c.stroke() + c.save();c.translate(128,ly+32);c.scale(hb,hb);c.fillStyle='#111';c.beginPath();c.moveTo(0,16);c.bezierCurveTo(-26,-2,-14,-22,0,-10);c.bezierCurveTo(14,-22,26,-2,0,16);c.fill();c.restore() + c.lineWidth=7;c.fillStyle='#fff' + c.beginPath();c.moveTo(48,116);c.lineTo(128,172);c.lineTo(208,116);c.lineTo(208,206);c.quadraticCurveTo(208,216,198,216);c.lineTo(58,216);c.quadraticCurveTo(48,216,48,206);c.closePath();c.fill();c.stroke() + if(fy>=0)flap() +} diff --git a/gen/sparkle/shine.js b/gen/sparkle/shine.js new file mode 100644 index 0000000..ea68ed5 --- /dev/null +++ b/gen/sparkle/shine.js @@ -0,0 +1,16 @@ +// big sparkle pulsing in the middle while small sparkles pop in and out around it +const{sin,PI,max}=Math,T=2*PI +export const frames=20,delay=70 +const star=(c,x,y,r,a=0)=>{ + const k=r*.16;c.save();c.translate(x,y);c.rotate(a);c.beginPath();c.moveTo(0,-r) + for(const[px,py,qx,qy]of[[r,0,k,-k],[0,r,k,k],[-r,0,-k,k],[0,-r,-k,-k]])c.quadraticCurveTo(qx,qy,px,py) + c.restore();c.fill();c.stroke() +} +export default(c,t)=>{ + c.lineWidth=5 + for(const[x,y,r,o]of[[52,60,26,0],[206,54,20,.17],[214,176,28,.33],[60,190,22,.5],[150,222,16,.66],[96,30,14,.83]]){ + const s=max(0,sin(PI*((t*2+o)%1))) + if(s>.08)star(c,x,y,r*s,.3*s) + } + c.lineWidth=7;star(c,128,128,62+10*sin(t*T),.12*sin(t*T)) +} diff --git a/gen/spinner/load.js b/gen/spinner/load.js new file mode 100644 index 0000000..fc61d55 --- /dev/null +++ b/gen/spinner/load.js @@ -0,0 +1,15 @@ +// loading ring of dots with a fading trail, and a little face in the middle watching it go round +const{sin,cos,PI}=Math,T=2*PI +export const delay=60 +export default(c,t)=>{ + const h=t*T + c.lineWidth=5 + for(let k=0;k<10;k++){ + const a=k*T/10-PI/2,g=((t-k/10)%1+1)%1,r=5+13*(1-g)**1.6 + c.beginPath();c.arc(128+cos(a)*78,128+sin(a)*78,r,0,T);c.fill();c.stroke() + } + c.lineWidth=7;c.beginPath();c.arc(128,128,40,0,T);c.fill();c.stroke() + const ex=cos(h-PI/2)*5,ey=sin(h-PI/2)*5 + c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*13+ex,122+ey,6,0,T),c.fill() + c.lineWidth=5;c.beginPath();c.arc(128+ex*.5,140+ey*.5,6,0,T);c.stroke() +} diff --git a/public/balloon/float.gif b/public/balloon/float.gif new file mode 100644 index 0000000..5dbde0b Binary files /dev/null and b/public/balloon/float.gif differ diff --git a/public/balloon/float.webp b/public/balloon/float.webp new file mode 100644 index 0000000..4ea6601 Binary files /dev/null and b/public/balloon/float.webp differ diff --git a/public/bell/ring.gif b/public/bell/ring.gif new file mode 100644 index 0000000..e07db3b Binary files /dev/null and b/public/bell/ring.gif differ diff --git a/public/bell/ring.webp b/public/bell/ring.webp new file mode 100644 index 0000000..3824bc5 Binary files /dev/null and b/public/bell/ring.webp differ diff --git a/public/bulb/idea.gif b/public/bulb/idea.gif new file mode 100644 index 0000000..60ac0f6 Binary files /dev/null and b/public/bulb/idea.gif differ diff --git a/public/bulb/idea.webp b/public/bulb/idea.webp new file mode 100644 index 0000000..9d1090f Binary files /dev/null and b/public/bulb/idea.webp differ diff --git a/public/check/done.gif b/public/check/done.gif new file mode 100644 index 0000000..02b4f40 Binary files /dev/null and b/public/check/done.gif differ diff --git a/public/check/done.webp b/public/check/done.webp new file mode 100644 index 0000000..fef94fc Binary files /dev/null and b/public/check/done.webp differ diff --git a/public/hourglass/flip.gif b/public/hourglass/flip.gif new file mode 100644 index 0000000..c8feb7a Binary files /dev/null and b/public/hourglass/flip.gif differ diff --git a/public/hourglass/flip.webp b/public/hourglass/flip.webp new file mode 100644 index 0000000..e254b77 Binary files /dev/null and b/public/hourglass/flip.webp differ diff --git a/public/mail/open.gif b/public/mail/open.gif new file mode 100644 index 0000000..e17ef37 Binary files /dev/null and b/public/mail/open.gif differ diff --git a/public/mail/open.webp b/public/mail/open.webp new file mode 100644 index 0000000..e0309ae Binary files /dev/null and b/public/mail/open.webp differ diff --git a/public/sparkle/shine.gif b/public/sparkle/shine.gif new file mode 100644 index 0000000..aa2625a Binary files /dev/null and b/public/sparkle/shine.gif differ diff --git a/public/sparkle/shine.webp b/public/sparkle/shine.webp new file mode 100644 index 0000000..4164fe2 Binary files /dev/null and b/public/sparkle/shine.webp differ diff --git a/public/spinner/load.gif b/public/spinner/load.gif new file mode 100644 index 0000000..66c18c0 Binary files /dev/null and b/public/spinner/load.gif differ diff --git a/public/spinner/load.webp b/public/spinner/load.webp new file mode 100644 index 0000000..2227632 Binary files /dev/null and b/public/spinner/load.webp differ