mirror of
https://github.com/direct-img/vibegif.direct-img.link.git
synced 2026-10-29 03:34:51 +00:00
Add 150 UI and page state stickers in three pending sections
404s, loaders, success, errors, empty states, confirmation, under construction, offline and more: 50 monochrome (ui), 50 colored (uicolor) and 50 with an anime girl (uianime), on /test until approved. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
// a closed door chained shut with a big padlock, it rattles as someone tries it but the lock just swings and holds
|
||||
const{sin,cos,PI,min,max,exp,hypot,atan2}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
const chain=(c,x0,y0,x1,y1,j)=>{
|
||||
const L=hypot(x1-x0,y1-y0),n=Math.round(L/17),a=atan2(y1-y0,x1-x0)
|
||||
for(const odd of[1,0])for(let k=odd;k<=n;k+=2){
|
||||
const v=k/n,x=x0+(x1-x0)*v,y=y0+(y1-y0)*v+j*sin(PI*v)
|
||||
c.save();c.translate(x,y);c.rotate(a)
|
||||
if(odd){c.lineWidth=13;c.beginPath();c.moveTo(-8,0);c.lineTo(8,0);c.stroke()}
|
||||
else{c.lineWidth=5;c.beginPath();c.ellipse(0,0,12,8,0,0,T);c.fill();c.stroke();c.lineWidth=4;c.beginPath();c.moveTo(-4,0);c.lineTo(4,0);c.stroke()}
|
||||
c.restore()
|
||||
}
|
||||
}
|
||||
export default(c,t,i)=>{
|
||||
const u=t*2%1,sh=u<.3?(i%2?3:-3):0,a=.34*sin(3*T*t)*exp(-2.6*u),j=sh*.7
|
||||
if(sh)for(const d of[-1,1])for(const y of[84,112,140])for(const[w,k]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(128+d*(100+(i%2)*3),y),c.lineTo(128+d*(114+(i%2)*3),y-6),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.roundRect(46,12,164,232,[30,30,4,4]);c.fill();c.stroke()
|
||||
c.save();c.translate(sh,0)
|
||||
c.beginPath();c.roundRect(60,26,136,218,[20,20,2,2]);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.roundRect(76,44,104,64,10);c.roundRect(76,124,104,100,10);c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.arc(176,140,9,0,T);c.fill();c.stroke()
|
||||
chain(c,72,52,184,214,j);chain(c,184,52,72,214,-j)
|
||||
c.fillStyle='#111';for(const[x,y]of[[72,52],[184,52],[72,214],[184,214]])c.beginPath(),c.arc(x,y,7,0,T),c.fill()
|
||||
c.fillStyle='#fff';c.restore()
|
||||
c.save();c.translate(128+sh,128);c.rotate(a)
|
||||
for(const[w,k]of[[30,'#111'],[16,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(-20,34),c.lineTo(-20,20),c.arc(0,20,20,PI,0),c.lineTo(20,34),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.beginPath();c.roundRect(-36,30,72,58,14);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(0,52,9,0,T);c.moveTo(-5,56);c.lineTo(-8,76);c.lineTo(8,76);c.lineTo(5,56);c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// a little 404 signpost stands by a hole; a mole pops up, looks left and right, shrugs and ducks back down
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=32,delay=70
|
||||
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||
const HX=172,HY=198
|
||||
const Q=(c,x,y,s)=>{
|
||||
c.save();c.translate(x,y);c.scale(s,s)
|
||||
for(const[w,st]of[[18,'#111'],[7,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.arc(0,-10,10,PI,PI*2.3),c.quadraticCurveTo(0,3,0,8),c.stroke()
|
||||
c.lineWidth=5;c.strokeStyle='#111';c.beginPath();c.arc(0,22,5.5,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const up=bk((t-.08)/.12)-io((t-.8)/.08),lk=sin(T*cl((t-.24)/.24)),sh=min(1,2.2*sin(PI*cl((t-.52)/.24))),u0=cl((t-.1)/.3),wb=.05*sin(T*2*u0)*(1-u0)
|
||||
c.beginPath();c.roundRect(10,178,236,54,27);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const[x,y]of[[32,214],[58,222],[112,218],[228,214]])c.beginPath(),c.arc(x,y,3.5,0,T),c.fill()
|
||||
c.beginPath();c.ellipse(HX,HY,48,13,0,0,T);c.fill();c.fillStyle='#fff'
|
||||
c.lineWidth=6;for(const[x,r]of[[HX-56,13],[HX+57,10]])c.beginPath(),c.arc(x,HY+4,r,PI,0),c.closePath(),c.fill(),c.stroke()
|
||||
c.lineWidth=7
|
||||
c.save();c.translate(72,204);c.rotate(.02+wb);c.translate(-72,-204)
|
||||
c.beginPath();c.roundRect(65,110,14,96,4);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(20,62,104,56,10);c.fill();c.stroke()
|
||||
c.lineWidth=9;for(const x of[42,102])c.beginPath(),c.moveTo(x+7,104),c.lineTo(x+7,76),c.lineTo(x-11,96),c.lineTo(x+11,96),c.stroke()
|
||||
c.beginPath();c.ellipse(72,90,8,14,0,0,T);c.stroke()
|
||||
c.restore()
|
||||
const v=cl((t-.08)/.2)
|
||||
if(v>0&&v<1){c.lineWidth=4;for(const[d,h]of[[-1,40],[1,52],[-.5,58],[.6,34]])c.beginPath(),c.arc(HX+d*(26+34*v),HY-4-h*sin(PI*v)+20*v*v,6*(1-v**3),0,T),c.fill(),c.stroke()}
|
||||
if(up>.01){
|
||||
c.save();c.beginPath();c.rect(0,0,256,HY);c.ellipse(HX,HY,48,13,0,0,T);c.clip()
|
||||
c.translate(HX,HY+20+96*(1-up));c.rotate(.08*sh)
|
||||
c.lineWidth=7;c.beginPath();c.roundRect(-32,-106,64,130,32);c.fill();c.stroke()
|
||||
const e=7*lk
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*12+e,-72,4.5,0,T),c.fill()
|
||||
c.beginPath();c.ellipse(e*1.3,-58,11,8,0,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(e*1.3-4,-61,2.5,0,T);c.fill()
|
||||
c.lineWidth=3;c.beginPath();c.roundRect(e-6,-50,12,9,2);c.fill();c.stroke();c.beginPath();c.moveTo(e,-50);c.lineTo(e,-41);c.stroke()
|
||||
for(const d of[-1,1])for(const a of[-.15,.15])c.beginPath(),c.moveTo(e*1.3+d*14,-58+a*20),c.lineTo(e*1.3+d*26,-58+a*44),c.stroke()
|
||||
if(sh>.1){c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.arc(d*12+e,-80-4*sh,6,PI*1.2,PI*1.8),c.stroke()}
|
||||
for(const d of[-1,1]){
|
||||
c.save();c.translate(d*(30+14*sh),-10-38*sh);c.rotate(d*(-.2-.9*sh));c.lineWidth=5
|
||||
c.beginPath();c.ellipse(0,0,14,10,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=3;for(const k of[-5,0,5])c.beginPath(),c.moveTo(k,-9),c.lineTo(k,-15),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
c.restore()
|
||||
}
|
||||
if(sh>.05)Q(c,HX+50,74,sh)
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// a magnifying glass sweeps back and forth over 404, and when it hovers the 0 it swells up big with a confused little face
|
||||
const{sin,PI,max,abs}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const N=(c,g)=>{for(const[w,s]of[[28,'#111'],[14,'#fff']]){
|
||||
c.lineWidth=w;c.strokeStyle=s
|
||||
for(const x of[60,196])c.beginPath(),c.moveTo(x+8,150),c.lineTo(x+8,78),c.lineTo(x-20,126),c.lineTo(x+20,126),c.stroke()
|
||||
c.beginPath();c.ellipse(128,114,22+14*g,36+6*g,0,0,T);c.stroke()
|
||||
}}
|
||||
const Q=(c,x,y,s,a)=>{
|
||||
c.save();c.translate(x,y);c.rotate(a);c.scale(s,s)
|
||||
for(const[w,st]of[[20,'#111'],[8,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.arc(0,-10,11,PI,PI*2.3),c.quadraticCurveTo(0,4,0,9),c.stroke()
|
||||
c.lineWidth=5;c.strokeStyle='#111';c.beginPath();c.arc(0,24,6,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const s=sin(T*t)**3,lx=128+58*s,ly=112,g=max(0,1-abs(lx-128)/30)**1.5,m=1.6
|
||||
N(c,0)
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.save();c.translate(lx,ly);c.rotate(1.25+.3*s)
|
||||
c.beginPath();c.roundRect(56,-9,20,18,3);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(74,-15,52,30,13);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const u of[90,104])c.beginPath(),c.moveTo(u,-8),c.lineTo(u,8),c.stroke()
|
||||
c.restore()
|
||||
c.save();c.beginPath();c.arc(lx,ly,52,0,T);c.fill();c.clip()
|
||||
c.translate(lx,ly);c.scale(m,m);c.translate(-lx,-ly);N(c,g)
|
||||
if(g>.05){
|
||||
c.translate(128,114);c.scale(1.25*g,1.25*g);c.fillStyle='#111'
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(d*7,-5,3.5,0,T),c.fill()
|
||||
c.lineWidth=2.5;c.strokeStyle='#111'
|
||||
c.beginPath();c.moveTo(-11,-14);c.lineTo(-4,-17);c.moveTo(4,-12);c.lineTo(11,-12);c.stroke()
|
||||
c.beginPath();c.moveTo(-8,9);c.lineTo(-4,6);c.lineTo(0,9);c.lineTo(4,6);c.lineTo(8,9);c.stroke()
|
||||
}
|
||||
c.restore()
|
||||
c.strokeStyle='#111';c.lineWidth=18;c.beginPath();c.arc(lx,ly,52,0,T);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=6;c.stroke()
|
||||
c.strokeStyle='#ddd';c.lineWidth=7;c.beginPath();c.arc(lx,ly,38,PI*1.1,PI*1.4);c.stroke()
|
||||
if(g>.3)Q(c,lx+52,ly-62,(g-.3)/.7,.2*sin(T*t*2))
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// a signpost whose arrow boards keep swinging round to point every which way, while a question mark bobs on top
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const bk=u=>(u=min(1,max(0,u)),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||
const B=[[112,94,0,-.12,[[.02,1],[.5,1]]],[154,82,PI,.1,[[.18,2],[.66,-2]]],[196,90,0,-.05,[[.34,1],[.84,1]]]]
|
||||
export default(c,t)=>{
|
||||
const bs=B.map(([y,L,b,tl,S])=>[y,L,b+S.reduce((a,[t0,n])=>a+n*PI*bk((t-t0)/.14),0),tl])
|
||||
const board=([y,L,a,tl])=>{
|
||||
const k=cos(a),P=[[-14,-16],[L-22,-16],[L,0],[L-22,16],[-14,16]]
|
||||
c.lineWidth=7;c.beginPath();for(const[u,v]of P)c.lineTo(128+u*k,y+v+u*k*tl);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(128+16*k,y+16*k*tl);c.lineTo(128+(L-34)*k,y+(L-34)*k*tl);c.stroke()
|
||||
}
|
||||
c.beginPath();c.roundRect(52,214,152,24,12);c.fill();c.stroke()
|
||||
for(const b of bs)if(sin(b[2])<0)board(b)
|
||||
c.lineWidth=7;c.beginPath();c.roundRect(118,86,20,140,6);c.fill();c.stroke()
|
||||
for(const b of bs)if(sin(b[2])>=0)board(b)
|
||||
c.save();c.translate(128,50+5*sin(T*t*2));c.rotate(.18*sin(T*t));c.scale(.88,.88)
|
||||
for(const[w,st]of[[24,'#111'],[11,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.arc(0,-12,12,PI,PI*2.3),c.quadraticCurveTo(0,2,0,8),c.stroke()
|
||||
c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.arc(0,24,7,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// chunky 404 digits stand in the desert like rocks under a hot sun while a tumbleweed bounces across in front, kicking up dust puffs
|
||||
const{sin,cos,PI,min}=Math,T=2*PI
|
||||
export const frames=18,delay=70
|
||||
const X=t=>-46+348*t
|
||||
const weed=(c,x,y,r,a,s)=>{
|
||||
c.save();c.translate(x,y+r);c.scale(2-s,s);c.translate(0,-r);c.rotate(a)
|
||||
c.beginPath();for(let k=0;k<36;k++){const b=k*T/36,q=r*(1+.05*sin(b*7));c.lineTo(cos(b)*q,sin(b)*q)}
|
||||
c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const[u,v,R,a]of[[.25,.15,.55,0],[-.3,.1,.5,2.2],[.05,-.3,.5,4],[-.1,.3,.42,1],[.1,0,.72,3.4]])c.beginPath(),c.arc(u*r,v*r,R*r,a,a+3),c.stroke()
|
||||
c.lineWidth=5;for(const b of[.4,2.3,4.1,5.4])c.beginPath(),c.moveTo(cos(b)*r,sin(b)*r),c.lineTo(cos(b+.25)*(r+8),sin(b+.25)*(r+8)),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
c.save();c.translate(210,42)
|
||||
for(let k=0;k<8;k++){const a=k*T/8;for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(cos(a)*21,sin(a)*21),c.lineTo(cos(a)*27,sin(a)*27),c.stroke()}
|
||||
c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.arc(0,0,14,0,T);c.fill();c.stroke();c.restore()
|
||||
c.lineWidth=7;c.beginPath();c.roundRect(10,190,236,46,23);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const[x,y]of[[30,214],[92,226],[160,222],[228,214]])c.beginPath(),c.arc(x,y,3.5,0,T),c.fill()
|
||||
c.fillStyle='#fff'
|
||||
for(const[x,a,z]of[[50,-.07,0],[128,.03,1],[206,.07,0]]){
|
||||
c.save();c.translate(x,202);c.rotate(a)
|
||||
for(const[w,s]of[[34,'#111'],[20,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();z?c.ellipse(0,-52,22,52,0,0,T):(c.moveTo(12,0),c.lineTo(12,-104),c.lineTo(-24,-36),c.lineTo(24,-36));c.stroke()}
|
||||
c.restore()
|
||||
}
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
const q=t*3%1,x=X(t),r=30,y=230-r-76*4*q*(1-q),e=min(q,1-q),s=e<.07?.8+.2*e/.07:1
|
||||
const lx=X(Math.floor(t*3)/3),p=q/.5
|
||||
if(p<1){c.lineWidth=5;for(const d of[-1,1])for(const[o,v,R]of[[16,30,12],[30,44,8]])c.beginPath(),c.arc(lx+d*(o+v*p),226-(R+4)*p,R*(1-p)+1,0,T),c.fill(),c.stroke()}
|
||||
for(const[dy,L]of[[-10,24],[8,16]])for(const[w,st]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(x-r-14,y+dy),c.lineTo(x-r-14-L,y+dy),c.stroke()
|
||||
c.lineWidth=6;c.strokeStyle='#111'
|
||||
weed(c,x,y,r,x/r,s)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// overheated server tower with dizzy x eyes, its lights blinking erratically, trembling while puffs of smoke rise from the top
|
||||
const{sin,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
export default(c,t,i)=>{
|
||||
const P=[0,1,2].map(k=>{const p=(t+k/3)%1,r=19*sin(PI*p)**.7;return[(k%2?150:110)+16*sin(T*p+k*2)*p,76-54*p,r]})
|
||||
for(const f of[0,1])for(const[x,y,r]of P)if(r>1)for(const[dx,dy,q]of[[-r*.6,r*.15,.7],[r*.6,r*.15,.7],[0,-r*.2,.9]]){c.beginPath();c.arc(x+dx,y+dy,r*q,0,T);f?(c.fillStyle='#ddd',c.fill()):(c.lineWidth=14,c.stroke())}
|
||||
c.lineWidth=7;c.fillStyle='#fff'
|
||||
c.translate(i%2?1.5:-1.5,0)
|
||||
for(const x of[84,172])c.beginPath(),c.roundRect(x-12,214,24,20,6),c.fill(),c.stroke()
|
||||
c.beginPath();c.roundRect(62,74,132,150,16);c.fill();c.stroke()
|
||||
for(let k=0;k<2;k++){
|
||||
const y=88+k*38
|
||||
c.beginPath();c.roundRect(76,y,104,28,8);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(88,y+14);c.lineTo(124,y+14);c.stroke()
|
||||
for(let j=0;j<2;j++){c.beginPath();c.arc(146+j*18,y+14,5.5,0,T);c.fillStyle=(i*7+k*5+j*3)%5<2?'#111':'#fff';c.fill();c.stroke()}
|
||||
c.fillStyle='#fff';c.lineWidth=7
|
||||
}
|
||||
c.lineWidth=6;for(const x of[106,150])c.beginPath(),c.moveTo(x-8,170),c.lineTo(x+8,186),c.moveTo(x+8,170),c.lineTo(x-8,186),c.stroke()
|
||||
c.lineWidth=5;c.beginPath();for(let k=0;k<=6;k++)c.lineTo(110+k*6,204+(k%2?-4:3));c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// notification bell fast asleep, no badge, gently rocking and breathing with a snot bubble while Zzz float up
|
||||
const{sin,PI,max}=Math,T=2*PI
|
||||
export const frames=20,delay=90
|
||||
export default(c,t)=>{
|
||||
const D=(f,a=13,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'}
|
||||
for(const k of[0,1,2]){
|
||||
const p=(t+k/3)%1,s=(6+10*p)*max(0,sin(PI*p))**.4,x=164+54*p+6*sin(T*p),y=108-84*p
|
||||
if(s>1)D(()=>{c.moveTo(x-s,y-s);c.lineTo(x+s,y-s);c.lineTo(x-s,y+s);c.lineTo(x+s,y+s)},s>8?14:12,s>8?6:5)
|
||||
}
|
||||
const br=sin(T*t),S=1.1
|
||||
c.translate(108,36);c.rotate(.04*br);c.scale(S,S*(1+.02*br));c.lineWidth=7/S
|
||||
c.beginPath();c.arc(0,160,13,0,T);c.fill();c.stroke()
|
||||
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/S;c.beginPath();c.moveTo(-28,40);c.quadraticCurveTo(-34,62,-35,84);c.stroke()
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(d*16,78,7,.1*PI,.9*PI),c.stroke()
|
||||
c.fillStyle='#ddd';for(const d of[-1,1])c.beginPath(),c.ellipse(d*25,92,6,4,0,0,T),c.fill()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(0,100,4.5,3.5+.8*br,0,0,T);c.fill()
|
||||
const b=5+6*(1+br)/2;c.fillStyle='#fff';c.lineWidth=4/S;c.beginPath();c.arc(8+b*.8,102,b,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=2.5/S;c.beginPath();c.arc(8+b*.8-b*.35,102-b*.35,b*.35,PI,1.5*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// cardboard box flaps pop open on an empty box, a spider drops in on its thread and dangles inside, climbs back out and the flaps close
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const cl=u=>min(1,max(0,u)),ease=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),back=u=>(u=cl(u),1+2.6*(u-1)**3+1.6*(u-1)**2)
|
||||
const G=232,W=72,H=84,Z=70,F=36,S=42,P=(x,y,z)=>[116+x+z*.32,G-y-z*.5]
|
||||
export default(c,t)=>{
|
||||
const o=back((t-.02)/.12)-ease((t-.86)/.12),dn=back((t-.14)/.16)-cl((t-.7)/.14)**2,sx=127,sy=-36+164*dn+6*sin(2*T*t)*dn
|
||||
const q=Q=>{c.beginPath();for(const p of Q)c.lineTo(...P(...p));c.closePath();c.fill();c.stroke()}
|
||||
const fb=(z,d,a)=>{const y=H+sin(a)*F,w=z+d*cos(a)*F;q([[-W,H,z],[W,H,z],[W,y,w],[-W,y,w]])}
|
||||
const fs=(d,a)=>{const x=d*W-d*cos(a)*S,y=H+sin(a)*S;q([[d*W,H,0],[d*W,H,Z],[x,y,Z],[x,y,0]])}
|
||||
fb(Z,-1,o*1.9)
|
||||
c.fillStyle='#999';q([[-W,H,0],[W,H,0],[W,H,Z],[-W,H,Z]]);c.fillStyle='#fff'
|
||||
if(dn>0){
|
||||
for(const[l,s]of[[6,'#111'],[2,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(sx,0),c.lineTo(sx,sy-18),c.stroke()
|
||||
const L=[]
|
||||
for(const d of[-1,1])for(let k=0;k<4;k++){const wg=5*sin(2*T*t+k*1.3+(d>0?1:0)),by=sy-8+k*6;L.push([[sx+d*14,by],[sx+d*(38+k*2),sy-24+k*12+wg*.5],[sx+d*(54-k*2),sy-6+k*16+wg]])}
|
||||
const pl=p=>{c.beginPath();c.moveTo(...p[0]);c.lineTo(...p[1]);c.lineTo(...p[2])}
|
||||
c.strokeStyle='#fff';c.lineWidth=14;for(const p of L)pl(p),c.stroke()
|
||||
c.beginPath();c.ellipse(sx,sy,24,21,0,0,T);c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=6;for(const p of L)pl(p),c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(sx,sy,24,21,0,0,T);c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(sx+d*9,sy-3,7,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(sx+d*8,sy-1,4,0,T),c.fill()
|
||||
c.strokeStyle='#fff';c.lineWidth=3;c.beginPath();c.arc(sx,sy+6,5,.15*PI,.85*PI);c.stroke()
|
||||
c.strokeStyle='#111';c.fillStyle='#fff';c.lineWidth=7
|
||||
}
|
||||
q([[W,0,0],[W,0,Z],[W,H,Z],[W,H,0]])
|
||||
q([[-W,0,0],[W,0,0],[W,H,0],[-W,H,0]])
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(116+d*26,G-30,6.5,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();dn>.3?c.ellipse(116,G-14,6,7,0,0,T):c.arc(116,G-21,9,.15*PI,.85*PI);c.stroke();c.lineWidth=7;c.fillStyle='#fff'
|
||||
fb(0,1,o*3.6)
|
||||
for(const d of[-1,1])fs(d,o*2.2)
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// video player stuck buffering: a ring of dots spins where the play button would be while the scrubber sits frozen partway
|
||||
const{cos,sin,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t)=>{
|
||||
c.beginPath();c.roundRect(14,36,228,184,20);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.roundRect(28,50,200,124,10);c.fill()
|
||||
c.fillStyle='#fff'
|
||||
for(let k=0;k<8;k++){const a=k*T/8-PI/2,g=((t-k/8)%1+1)%1;c.beginPath();c.arc(128+cos(a)*34,112+sin(a)*34,4+8*(1-g)**1.6,0,T);c.fill()}
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(34,186);c.lineTo(34,208);c.lineTo(53,197);c.closePath();c.fill();c.stroke()
|
||||
c.lineCap='round';c.lineWidth=12
|
||||
for(const[a,b,s]of[[74,222,'#ddd'],[74,168,'#999'],[74,132,'#111']])c.strokeStyle=s,c.beginPath(),c.moveTo(a,197),c.lineTo(b,197),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.arc(132,197,11,0,T);c.fill();c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// 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)flip(c,a)
|
||||
for(const d of[-1,1])c.beginPath(),c.roundRect(X+d*44-9,34,18,40,9),c.fill(),c.stroke()
|
||||
c.beginPath();c.roundRect(X-W/2-12,58,W+24,50,14);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(X+d*44,72,6,0,7),c.fill()
|
||||
c.fillStyle='#fff'
|
||||
if(a>=PI/2&&a<=PI)flip(c,a)
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// empty shopping cart rolling back and forth on its own, wheels spinning, leaving little dust puffs behind its wheels
|
||||
const{sin,cos,PI,min}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
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 S=.94,x=140+14*sin(T*t),G=216,a=(x-140)/(15*S)
|
||||
D(()=>{c.moveTo(18,G+6);c.lineTo(238,G+6)},11,4)
|
||||
c.translate(x,G);c.rotate(.03*sin(T*t));c.scale(S,S);const w=7/S;c.lineWidth=w
|
||||
const D2=(f)=>D(f,20/S,7/S)
|
||||
D2(()=>{c.moveTo(-52,-78);c.lineTo(-56,-44);c.lineTo(70,-44)})
|
||||
D2(()=>{c.moveTo(-64,-140);c.lineTo(-86,-166)})
|
||||
c.lineWidth=w;c.beginPath();c.roundRect(-106,-176,32,16,8);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(-66,-140);c.lineTo(80,-140);c.lineTo(64,-78);c.lineTo(-52,-78);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5/S;for(const u of[.25,.5,.75])c.beginPath(),c.moveTo(-66+146*u,-140),c.lineTo(-52+116*u,-78),c.stroke()
|
||||
c.beginPath();c.moveTo(-59,-109);c.lineTo(72,-109);c.stroke()
|
||||
for(const wx of[-38,54]){
|
||||
c.lineWidth=w;c.beginPath();c.arc(wx,-17,15,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4/S;c.beginPath();for(const k of[0,1])c.moveTo(wx+cos(a+k*PI/2)*9,-17+sin(a+k*PI/2)*9),c.lineTo(wx-cos(a+k*PI/2)*9,-17-sin(a+k*PI/2)*9);c.stroke()
|
||||
}
|
||||
c.setTransform(1,0,0,1,0,0);c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
for(const[o,d]of[[0,1],[.5,-1]]){
|
||||
const q=((t-o)%1+1)%1/.4,g=sin(PI*min(1,q)),wx=140+(d>0?-44:59)
|
||||
if(q<1)for(const[k,r]of[[0,14],[1,10],[2,8]])if(r*g>1)c.lineWidth=5,c.beginPath(),c.arc(wx-d*(k*12+8*q),G-6-(k==1?9:0)-8*q,r*g,0,T),c.fill(),c.stroke()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// 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()
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// closed stage curtains sway and twitch as if they're about to part, while a spotlight wobbles across them
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
export default(c,t)=>{
|
||||
const g=3+9*max(0,sin(T*t))**3,sp=[128+34*sin(T*t),132+18*sin(2*T*t+1),50+4*sin(3*T*t)]
|
||||
const cur=d=>{
|
||||
c.beginPath();c.moveTo(128+d*118,44);c.lineTo(128+d*118,222)
|
||||
const ix=y=>128+d*(g+(y-44)/178*10*(1+sin(T*t))+3*sin(y/26-T*t*2))
|
||||
c.lineTo(128+d*118,224);c.quadraticCurveTo(128+d*(g+60),232,ix(222),222)
|
||||
for(let y=222;y>=44;y-=6)c.lineTo(ix(y),y)
|
||||
c.closePath()
|
||||
}
|
||||
c.fillStyle='#111';c.fillRect(20,40,216,184)
|
||||
for(const d of[-1,1]){
|
||||
cur(d);c.fillStyle='#bbb';c.fill()
|
||||
c.save();c.clip()
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(sp[0],sp[1],sp[2],sp[2]*1.1,0,0,T);c.fill()
|
||||
c.strokeStyle='#888';c.lineWidth=8
|
||||
for(const f of[.3,.58,.84]){c.beginPath();for(let y=44;y<=230;y+=6)c.lineTo(128+d*(g+f*108+(y-44)*.04*(1+sin(T*t))+3*sin(y/26-T*t*2+f*5)),y);c.stroke()}
|
||||
c.restore();c.strokeStyle='#111';c.lineWidth=7;cur(d);c.stroke()
|
||||
}
|
||||
c.fillStyle='#fff'
|
||||
c.beginPath();c.roundRect(8,218,240,28,8);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(18,230);c.lineTo(238,230);c.stroke();c.lineWidth=7
|
||||
c.beginPath();c.moveTo(8,14);c.lineTo(248,14);c.lineTo(248,50)
|
||||
for(let k=0;k<5;k++)c.arc(248-24-k*48,50,24,0,PI)
|
||||
c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(16,30);c.lineTo(240,30);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// 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()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// a little traffic cone sways beside a striped road barrier while the warning lamp on top blinks on and off
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
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 on=i%8<4,sw=.05*sin(t*T*2),cx=(y,d)=>70+d*(10+(y-46)*.17)
|
||||
for(const[x,d]of[[122,-1],[214,1]])ln(c,18,()=>{c.moveTo(x,130);c.lineTo(x+d*14,234)})
|
||||
c.save();c.beginPath();c.roundRect(94,104,150,40,10);c.fill();c.clip()
|
||||
c.fillStyle='#111';for(let x=80;x<260;x+=36)c.beginPath(),c.moveTo(x,104),c.lineTo(x+18,104),c.lineTo(x-4,144),c.lineTo(x-22,144),c.fill()
|
||||
c.restore();c.beginPath();c.roundRect(94,104,150,40,10);c.stroke()
|
||||
if(on)for(const a of[-2.8,-2.2,-1.57,-.94,-.34])ln(c,11,()=>{c.moveTo(208+cos(a)*32,80+sin(a)*32);c.lineTo(208+cos(a)*46,80+sin(a)*46)})
|
||||
c.fillStyle=on?'#fff':'#888';c.beginPath();c.arc(208,84,20,PI,0);c.lineTo(228,92);c.lineTo(188,92);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.roundRect(184,90,48,16,5);c.fill();c.stroke()
|
||||
if(on){c.lineWidth=5;c.beginPath();c.arc(208,84,11,PI*1.15,PI*1.45);c.stroke();c.lineWidth=7}
|
||||
c.translate(70,228);c.rotate(sw);c.translate(-70,-228)
|
||||
c.beginPath();c.roundRect(14,212,112,22,8);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(cx(46,-1),46);c.lineTo(cx(46,1),46);c.lineTo(cx(214,1),214);c.lineTo(cx(214,-1),214);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.moveTo(cx(90,-1),90);c.lineTo(cx(90,1),90);c.lineTo(cx(118,1),118);c.lineTo(cx(118,-1),118);c.fill()
|
||||
const e=on?2:-1;for(const d of[-1,1])c.beginPath(),c.arc(70+d*13+e,160-(on?2:0),5.5,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(70+e,172,9,.15*PI,.85*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// a tower crane lowers a content block into the empty slot of a half-built web page, the page scrolls down to make room and a fresh block pops onto the hook
|
||||
const{sin,PI,min,max}=Math,T=2*PI
|
||||
export const frames=28,delay=70
|
||||
const ease=u=>(u=min(1,max(0,u)),u<.5?2*u*u:1-2*(1-u)**2)
|
||||
const back=u=>(u=min(1,max(0,u)),1+2.7*(u-1)**3+1.7*(u-1)**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 brick=(c,x,y)=>{
|
||||
c.lineWidth=5;c.beginPath();c.roundRect(x,y,124,26,6);c.fill();c.stroke()
|
||||
c.fillStyle='#bbb';c.beginPath();c.roundRect(x+8,y+6,24,14,3);c.fill();c.fillStyle='#fff'
|
||||
c.strokeStyle='#bbb';for(const[d,w]of[[9,72],[17,48]])c.beginPath(),c.moveTo(x+42,y+d),c.lineTo(x+42+w,y+d),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const p=ease(t/.42),land=t>=.5,o=32*ease((t-.54)/.28),sx=land?0:6*sin(T*t/.42*1.5)*(1-p)
|
||||
const hy=land?114-56*ease((t-.5)/.3):58+56*p,sc=t>.82?back((t-.82)/.16):1
|
||||
c.beginPath();c.roundRect(14,100,152,138,12);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(14,122);c.lineTo(166,122);c.stroke()
|
||||
c.fillStyle='#111';for(const x of[30,44,58])c.beginPath(),c.arc(x,111,4,0,T),c.fill()
|
||||
c.fillStyle='#fff';c.save();c.beginPath();c.rect(18,124,144,110);c.clip()
|
||||
for(let k=-2;k<4;k++){
|
||||
const y=132+32*k+o
|
||||
if(k>0||k==0&&land)brick(c,28,y)
|
||||
else c.setLineDash([8,7]),c.lineWidth=4,c.strokeStyle='#888',c.beginPath(),c.roundRect(28,y,124,26,6),c.stroke(),c.setLineDash([]),c.strokeStyle='#111'
|
||||
}
|
||||
c.restore()
|
||||
if(t>.42&&t<.56)for(const d of[-1,1]){const u=(t-.42)/.14;c.lineWidth=5;c.beginPath();c.arc(90+d*(66+10*u),156-6*u,7*(1-u)+3,0,T);c.fill();c.stroke()}
|
||||
c.lineWidth=7
|
||||
ln(c,9,()=>{c.moveTo(24,34);c.lineTo(200,14);c.lineTo(244,34)})
|
||||
c.beginPath();c.roundRect(188,40,24,196,4);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();for(let y=40;y<230;y+=24)c.moveTo(188,y),c.lineTo(212,y+12),c.lineTo(188,y+24);c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.roundRect(172,226,56,14,5);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(20,30,228,14,4);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();for(let x=26;x<240;x+=16)c.moveTo(x,31),c.lineTo(x+8,43),c.lineTo(x+16,31);c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.roundRect(220,44,24,26,4);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(200,12);c.lineTo(212,30);c.lineTo(188,30);c.closePath();c.fill();c.stroke()
|
||||
const hx=90+sx
|
||||
ln(c,9,()=>{c.moveTo(90,52);c.lineTo(hx,hy-10)})
|
||||
c.beginPath();c.roundRect(78,42,24,12,4);c.fill();c.stroke()
|
||||
if(!land||t>.82){
|
||||
c.save();c.translate(hx,hy+31);c.scale(sc,sc);c.translate(-hx,-hy-31)
|
||||
ln(c,8,()=>{c.moveTo(hx-50,hy+18);c.lineTo(hx,hy);c.lineTo(hx+50,hy+18)})
|
||||
brick(c,hx-62,hy+18);c.restore()
|
||||
}
|
||||
ln(c,11,()=>{c.moveTo(hx,hy-12);c.lineTo(hx,hy);c.arc(hx-6,hy,6,0,PI*.9)})
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// browser window with a dizzy sad face: a crack zigzags down it while it shakes, both halves sag apart, then it blinks off and reloads
|
||||
const{sin,PI,min,max,hypot}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const cl=u=>min(1,max(0,u)),ease=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),back=u=>(u=cl(u),1+3*(u-1)**3+2*(u-1)**2)
|
||||
const K=[[150,30],[150,44],[140,70],[154,96],[134,122],[148,148],[128,174],[140,212],[140,240]],B=[[[154,96],[178,90],[194,104]],[[134,122],[110,128],[96,118]],[[148,148],[170,160],[176,180]]]
|
||||
const len=P=>P.slice(1).reduce((s,p,k)=>s+hypot(p[0]-P[k][0],p[1]-P[k][1]),0),LK=len(K.slice(1,8))
|
||||
export default(c,t,i)=>{
|
||||
const r=t<.9,p=r?cl((t-.08)/.26):0,g=r?ease((t-.36)/.1):0,wb=t>.36&&t<.84?.02*sin((t-.36)*T*4)*(1-cl((t-.4)/.4)):0,off=cl((t-.84)/.06),on=back((t-.9)/.1)
|
||||
const pl=P=>{c.beginPath();for(const q of P)c.lineTo(...q)}
|
||||
const W=()=>{
|
||||
c.beginPath();c.roundRect(24,44,208,168,14);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(24,72);c.lineTo(232,72);c.stroke()
|
||||
c.lineWidth=4;for(const k of[0,1,2])c.beginPath(),c.arc(42+k*16,58,5,0,T),c.stroke()
|
||||
c.beginPath();c.roundRect(96,51,122,14,7);c.stroke()
|
||||
c.lineWidth=7;for(const x of[96,162])c.beginPath(),c.moveTo(x-11,113),c.lineTo(x+11,135),c.moveTo(x+11,113),c.lineTo(x-11,135),c.stroke()
|
||||
c.lineWidth=6;c.beginPath();c.arc(129,194,24,1.2*PI,1.8*PI);c.stroke()
|
||||
if(p>0){
|
||||
c.lineWidth=9;c.setLineDash([LK*p,999]);pl(K.slice(1,8));c.stroke()
|
||||
B.forEach((b,k)=>{const q=cl((p-[.29,.46,.62][k])/.25);if(q>0)c.lineWidth=5,c.setLineDash([len(b)*q,999]),pl(b),c.stroke()})
|
||||
c.setLineDash([]);c.lineWidth=7
|
||||
}
|
||||
}
|
||||
if(t>=.9&&on<.02||t>.84&&t<.9&&off>.98)return
|
||||
const s=t<.84?1:t<.9?1-off:on,sy=t<.84||t>=.9?s:max(.03,1-off),sx=t<.84||t>=.9?s:1+.05*off
|
||||
c.translate(128+(t>.08&&t<.36?(i%2?3:-3):0),128);c.scale(sx*.94,sy*.94);c.translate(-128,-128)
|
||||
if(!g&&!wb)return W()
|
||||
for(const[d,px,py,a]of[[-1,24,44,.07*g+wb],[1,232,44,-.08*g-wb]]){
|
||||
c.save();c.translate(px,py);c.rotate(a);c.translate(-px,-py)
|
||||
pl([[d*999+128,0],...K,[d*999+128,256]]);c.clip();W();c.restore()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// a sheet of paper pops up and feeds into a chomping shredder, and thin wavy strips stream out the bottom into the bin
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const back=u=>(u=min(1,max(0,u)),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||
export default(c,t,i)=>{
|
||||
const H=84,s=back(t/.16),f=t<.2?0:min(210,(t-.2)/.58*210),go=t>.2&&t<.8,j=go?(i%2?2:-2):0
|
||||
if(f<H){
|
||||
c.save();c.beginPath();c.rect(0,0,256,100);c.clip()
|
||||
c.translate(128,54+f);c.scale(s,s);c.translate(-128,-54)
|
||||
c.beginPath();c.rect(80,12,96,H);c.fill();c.stroke()
|
||||
c.lineWidth=5;for(const[y,w]of[[30,60],[46,48],[62,60],[78,36]])c.beginPath(),c.moveTo(96,y),c.lineTo(96+w,y),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
c.save();c.beginPath();c.rect(0,146,256,70);c.clip();c.lineWidth=4
|
||||
for(let k=0;k<6;k++){
|
||||
const x=81+k*16,y0=96-H+f,y1=96+f,w=y=>2*sin(y*.1+k*2.1-T*t*3)
|
||||
if(y1<146||y0>216)continue
|
||||
c.beginPath();for(let y=max(y0,142);y<=min(y1,218);y+=4)c.lineTo(x+w(y),y);for(let y=min(y1,218);y>=max(y0,142);y-=4)c.lineTo(x+12+w(y),y);c.closePath();c.fill();c.stroke()
|
||||
}
|
||||
c.restore();c.lineWidth=5
|
||||
for(const[x,a]of[[86,-.6],[116,.3],[146,-.25],[172,.5]])c.save(),c.translate(x,216),c.rotate(a),c.beginPath(),c.roundRect(-5,-16,10,20,4),c.fill(),c.stroke(),c.restore()
|
||||
c.lineWidth=7
|
||||
c.beginPath();c.moveTo(48,208);c.lineTo(208,208);c.lineTo(196,244);c.lineTo(60,244);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5;for(const x of[96,128,160])c.beginPath(),c.moveTo(x,218),c.lineTo(x,234),c.stroke()
|
||||
c.translate(j,0);c.lineWidth=7
|
||||
c.beginPath();c.roundRect(22,96,212,56,18);c.fill();c.stroke()
|
||||
c.lineWidth=8;c.beginPath();c.moveTo(66,106);c.lineTo(190,106);c.stroke()
|
||||
c.fillStyle='#111'
|
||||
if(go){c.lineWidth=5;for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*36,120),c.lineTo(128+d*26,126),c.lineTo(128+d*36,132),c.stroke()
|
||||
c.beginPath();c.ellipse(128,138,9,i%2?7:3,0,0,T);c.fill()}
|
||||
else{for(const d of[-1,1])c.beginPath(),c.arc(128+d*28,124,6,0,T),c.fill();c.lineWidth=5;c.beginPath();c.arc(128,132,9,PI*.15,PI*.85);c.stroke()}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// clipboard checklist: the three boxes get ticked one by one, the clipboard does a happy hop, then the ticks pop away
|
||||
const{sin,PI,min,max,hypot}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const cl=u=>min(1,max(0,u)),L=hypot(9,10)+hypot(21,27)
|
||||
export default(c,t)=>{
|
||||
const h=t>.66&&t<.82?sin((t-.66)/.16*PI):0,out=1-cl((t-.88)/.08)
|
||||
c.translate(128,234-10*h);c.scale(1-.03*h,1+.02*h);c.translate(-128,-234)
|
||||
c.fillStyle='#ddd';c.beginPath();c.roundRect(50,52,156,182,16);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.roundRect(66,70,124,148,6);c.fill();c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.arc(128,40,16,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(92,44,72,26,9);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128,38,5,0,T);c.stroke()
|
||||
for(let k=0;k<3;k++){
|
||||
const y=104+k*48,s=.06+k*.18,p=cl((t-s)/.12),q=cl((t-s-.12)/.1),b=1+.22*sin(q*PI)
|
||||
c.save();c.translate(96,y);c.scale(b,b)
|
||||
c.lineWidth=6;c.beginPath();c.roundRect(-15,-15,30,30,7);c.fill();c.stroke();c.restore()
|
||||
c.lineWidth=10;c.strokeStyle='#bbb';c.beginPath();c.moveTo(126,y-6);c.lineTo([168,154,174][k],y-6);c.moveTo(126,y+8);c.lineTo([150,166,140][k],y+8);c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
if(p>0&&out>0){
|
||||
c.save();c.translate(96,y);c.scale(out,out);c.lineWidth=11;c.setLineDash([L*p,999])
|
||||
c.beginPath();c.moveTo(-10,-1);c.lineTo(-1,9);c.lineTo(20,-18);c.stroke();c.restore()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// a down arrow pops up and drops into a smiling tray, which squashes and bounces as it catches it
|
||||
const{sin,cos,PI,min,max,exp}=Math,T=2*PI
|
||||
export const frames=18,delay=70
|
||||
const back=u=>(u=min(1,max(0,u)),1+2.7*(u-1)**3+1.7*(u-1)**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'}
|
||||
export default(c,t)=>{
|
||||
const s=back(t/.16),v=max(0,(t-.14)/.3),y=58+142*v*v,h=t-.44,b=h>0?.16*exp(-7*h)*cos(h*T*3):0,hit=h>0&&h<.16
|
||||
c.translate(128,238);c.scale(1+b*.6,1-b);c.translate(-128,-238)
|
||||
c.fillStyle='#ddd';c.beginPath();c.roundRect(36,132,184,34,14);c.fill();c.stroke();c.fillStyle='#fff'
|
||||
if(v<1){
|
||||
c.save();c.beginPath();c.rect(0,0,256,226);c.clip()
|
||||
if(v>.25)for(const x of[-12,12])ln(c,11,()=>{c.moveTo(128+x,y-46);c.lineTo(128+x,y-46-34*v)})
|
||||
c.translate(128,y);c.scale(s,s)
|
||||
c.beginPath();c.moveTo(0,40);c.lineTo(36,2);c.lineTo(15,2);c.lineTo(15,-38);c.lineTo(-15,-38);c.lineTo(-15,2);c.lineTo(-36,2);c.closePath();c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
if(hit)for(const d of[-1,1])for(const a of[-.5,0,.5])ln(c,11,()=>{const q=-PI/2+d*(.9+a*.45);c.moveTo(128+d*96+cos(q)*14,134+sin(q)*14);c.lineTo(128+d*96+cos(q)*30,134+sin(q)*30)})
|
||||
c.beginPath();c.moveTo(24,150);c.lineTo(232,150);c.lineTo(214,236);c.lineTo(42,236);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.lineWidth=6
|
||||
if(hit)for(const d of[-1,1])c.beginPath(),c.arc(128+d*26,192,9,PI*1.15,PI*1.85),c.stroke()
|
||||
else for(const d of[-1,1])c.beginPath(),c.arc(128+d*26,188,7,0,T),c.fill()
|
||||
c.beginPath();if(hit)c.arc(128,200,11,0,PI),c.closePath(),c.fill();else c.arc(128,198,11,PI*.15,PI*.85),c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// a little beetle scuttles in a figure eight over a code editor, the line it's crawling on lights up as the buggy one
|
||||
const{sin,cos,PI,atan2,round,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const C=[[0,[28,1],[40,0],[22,0]],[1,[22,1],[58,0]],[2,[30,0],[18,1],[36,0]],[2,[46,0],[26,0]],[1,[16,1],[40,0]],[0,[12,1]],[0,[34,1],[50,0]]]
|
||||
export default(c,t)=>{
|
||||
const x=128+74*sin(T*t),y=148+44*sin(2*T*t),h=atan2(88*cos(2*T*t),74*cos(T*t)),r=min(6,max(0,round((y-88)/20))),st=sin(T*t*8)
|
||||
c.beginPath();c.roundRect(16,36,224,188,14);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(16,64);c.lineTo(240,64);c.stroke()
|
||||
c.lineWidth=4;for(const k of[0,1,2])c.beginPath(),c.arc(36+k*18,50,5,0,T),k?c.stroke():(c.fillStyle='#111',c.fill(),c.stroke())
|
||||
c.fillStyle='#ddd';c.beginPath();c.roundRect(26,79+r*20,204,18,5);c.fill()
|
||||
C.forEach(([n,...s],k)=>{
|
||||
const y=88+k*20;let x=60+n*18
|
||||
c.lineWidth=8;c.strokeStyle='#bbb';c.beginPath();c.moveTo(34,y);c.lineTo(42,y);c.stroke()
|
||||
for(const[l,d]of s)c.strokeStyle=d?'#111':'#aaa',c.beginPath(),c.moveTo(x,y),c.lineTo(x+l,y),c.stroke(),x+=l+12
|
||||
})
|
||||
c.strokeStyle='#111';c.lineWidth=3;c.beginPath();for(let k=0;k<=30;k++)c.lineTo(60+k*4,88+r*20+10+(k%2?2:-2));c.stroke()
|
||||
c.translate(x,y);c.rotate(h);c.scale(1.25,1.25)
|
||||
c.lineWidth=4.5
|
||||
for(const s of[-1,1])for(const k of[-1,0,1]){const g=(k+s)%2?st:-st;c.beginPath();c.moveTo(k*9,s*10);c.lineTo(k*12+g*6,s*22);c.lineTo(k*16+g*7,s*28);c.stroke()}
|
||||
for(const s of[-1,1]){c.beginPath();c.moveTo(26,s*5);c.quadraticCurveTo(36,s*8,40,s*16+st*2*s);c.stroke()}
|
||||
c.fillStyle='#111';c.lineWidth=6;c.beginPath();c.arc(22,0,11,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(-2,0,23,18,0,0,T);c.fill();c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=3;c.beginPath();c.moveTo(14,0);c.lineTo(-22,0);c.stroke()
|
||||
c.fillStyle='#fff';for(const[a,b,r]of[[2,-9,4],[-12,-8,3],[2,9,4],[-12,8,3]])c.beginPath(),c.arc(a,b,r,0,T),c.fill()
|
||||
for(const s of[-1,1])c.beginPath(),c.arc(26,s*5,4,0,T),c.fill();c.fillStyle='#111';for(const s of[-1,1])c.beginPath(),c.arc(28,s*5,2,0,T),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// round error badge with a big X shaking its head side to side like "nope nope", then pausing
|
||||
const{sin,PI,abs,min}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
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 u=min(1,t/.6),s=sin(T*u*3)*sin(PI*u)**.6
|
||||
if(abs(s)>.6){const d=s>0?-1:1;for(const r of[96,114])D(()=>c.arc(128+16*s,128,r,d>0?-.4:PI-.4,d>0?.4:PI+.4),11,4)}
|
||||
c.translate(128+16*s,128);c.rotate(.1*s);c.scale(1-.06*abs(s),1)
|
||||
c.beginPath();c.arc(0,0,84,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(0,0,70,0,T);c.stroke()
|
||||
c.translate(18*s,0);c.scale(1-.2*abs(s),1);c.lineWidth=26
|
||||
c.beginPath();c.moveTo(-30,-30);c.lineTo(30,30);c.moveTo(30,-30);c.lineTo(-30,30);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// broken robot slumped on the floor: head drooping, bent antenna sparking, one eye flickering, a loose spring boinging out of its head
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
const FL=[1,1,0,1,0,0,1,1,1,1,0,1,1,0,1,1],SP=[1,0,0,1,1,0,0,0,1,0,1,1,0,0,0,0]
|
||||
export default(c,t,i)=>{
|
||||
const D=(f,a=20,b=8)=>{for(const[l,s]of[[a,'#111'],[b,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
c.translate(-8,0)
|
||||
const br=2*sin(T*t),ha=.5+.04*sin(T*t-.6)
|
||||
for(const d of[-1,1]){D(()=>{c.moveTo(118+d*24,206);c.lineTo(118+d*44,220)});c.beginPath();c.roundRect(118+d*50-18,210,36,22,9);c.fill();c.stroke()}
|
||||
for(const d of[-1,1]){
|
||||
D(()=>{c.moveTo(118+d*44,160+br);c.quadraticCurveTo(118+d*66,176,118+d*66,206)})
|
||||
c.lineWidth=6;c.beginPath();c.arc(118+d*66,214,10,0,T);c.fill();c.stroke();c.lineWidth=7
|
||||
}
|
||||
c.beginPath();c.roundRect(72,144+br,92,70-br,14);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(100,168+br,6,0,T);c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(118,168+br,6,0,T);c.stroke()
|
||||
c.beginPath();c.moveTo(131,162+br);c.lineTo(141,172+br);c.moveTo(141,162+br);c.lineTo(131,172+br);c.stroke()
|
||||
for(const y of[188,198])c.beginPath(),c.moveTo(98,y+br*.5),c.lineTo(138,y+br*.5),c.stroke()
|
||||
c.fillStyle='#fff';c.lineWidth=7
|
||||
c.translate(126,146+br);c.rotate(ha)
|
||||
c.beginPath();c.rect(-8,-10,16,12);c.fill();c.stroke()
|
||||
c.save();c.translate(-44,-48);c.rotate(-1.75+.35*sin(2*T*t))
|
||||
D(()=>{for(let k=0;k<=60;k++){const u=k/60;c.lineTo(9*sin(u*T*4.5),-u*46)}},13,5)
|
||||
c.beginPath();c.arc(0,-52,9,0,T);c.fill();c.stroke();c.restore()
|
||||
D(()=>{c.moveTo(16,-70);c.lineTo(26,-92);c.lineTo(50,-90)},12,5)
|
||||
if(SP[i])for(let k=0;k<4;k++){const a=-1.6+k*1.05+(i%3)*.25,x=55+cos(a)*13,y=-90+sin(a)*13,p=a+1.4;D(()=>{c.moveTo(x,y);c.lineTo(x+cos(a)*10+cos(p)*5,y+sin(a)*10+sin(p)*5);c.lineTo(x+cos(a)*12-cos(p)*5,y+sin(a)*12-sin(p)*5);c.lineTo(x+cos(a)*19,y+sin(a)*19)},10,4)}
|
||||
c.beginPath();c.arc(55,-90,8,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(-46,-72,92,64,15);c.fill();c.stroke()
|
||||
c.fillStyle='#111'
|
||||
if(FL[i])c.beginPath(),c.roundRect(-28,-52,14,20,7),c.fill()
|
||||
else c.lineWidth=5,c.beginPath(),c.moveTo(-28,-41),c.lineTo(-14,-41),c.stroke()
|
||||
c.lineWidth=6;c.beginPath();c.moveTo(13,-51);c.lineTo(27,-35);c.moveTo(27,-51);c.lineTo(13,-35);c.stroke()
|
||||
c.lineWidth=5;c.beginPath();for(let k=0;k<=4;k++)c.lineTo(-14+k*7,-20+(k%2?-4:2));c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
// folder flap swings open showing nothing inside, a little moth flutters out and flies off, then the flap closes
|
||||
const{sin,cos,PI,min,max,abs}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const cl=u=>min(1,max(0,u)),ease=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2)
|
||||
const moth=(c,f)=>{
|
||||
for(const d of[-1,1]){
|
||||
for(const[w,s]of[[11,'#111'],[4,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.moveTo(d*3,-14);c.quadraticCurveTo(d*6,-26,d*16,-31);for(const k of[0,1,2]){const x=d*(6+k*4),y=-22-k*3.5;c.moveTo(x,y);c.lineTo(x+d*5,y+4)}c.stroke()}
|
||||
c.strokeStyle='#111';c.lineWidth=5
|
||||
c.save();c.scale(d*f,1)
|
||||
c.beginPath();c.moveTo(4,2);c.quadraticCurveTo(30,4,26,22);c.quadraticCurveTo(12,26,4,12);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(4,-8);c.lineTo(48,-20);c.quadraticCurveTo(48,2,8,6);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#bbb';c.beginPath();c.arc(30,-9,5,0,T);c.fill();c.fillStyle='#fff'
|
||||
c.lineWidth=3.5;c.beginPath();c.moveTo(14,-2);c.lineTo(40,-12);c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
c.lineWidth=5;c.beginPath();c.ellipse(0,2,8,18,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(0,-11,9,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=3.5;for(const y of[6,13])c.beginPath(),c.moveTo(-6,y),c.lineTo(6,y),c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*3.5,-12,2.3,0,T),c.fill()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const o=ease((t-.04)/.16)-ease((t-.84)/.12),u=(t-.2)/.6
|
||||
c.beginPath();c.roundRect(32,56,80,34,11);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(32,74,192,150,12);c.fill();c.stroke()
|
||||
if(o>0)c.fillStyle='#ddd',c.beginPath(),c.roundRect(40,84,176,136,8),c.fill(),c.fillStyle='#fff'
|
||||
const mo=()=>{if(u>0&&u<1){const s=cl(u/.1)*(1-.45*u)*(u>.9?1-(u-.9)/.1:1),x=128+34*sin(u*T*1.5)+40*u,y=150-112*u**.9
|
||||
c.save();c.translate(x,y);c.rotate(.25*sin(u*T*1.5+1));c.scale(s*1.25,s*1.25);moth(c,.3+.7*abs(cos(T*t*5)));c.restore();c.lineWidth=7}}
|
||||
if(u<.12)mo()
|
||||
const fy=1-.36*o
|
||||
c.save();c.translate(128,224);c.transform(1,0,-.12*o,fy,0,0)
|
||||
c.beginPath();c.roundRect(-96,-128,192,128,12);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),o>.5?c.ellipse(d*26,-68,7,9,0,0,T):c.ellipse(d*26,-64,7,7,0,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();o>.5?c.ellipse(0,-46,7,8,0,0,T):c.arc(0,-52,9,.15*PI,.85*PI);c.stroke()
|
||||
c.restore()
|
||||
if(u>=.12)mo()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// empty inbox tray looking bored while a fly buzzes loop-de-loops around it, leaving a dotted trail
|
||||
const{sin,cos,PI,atan2}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const F=u=>{const a=T*u;return[128+80*cos(a)+16*cos(4*a),116+60*sin(a)+18*sin(4*a)]}
|
||||
export default(c,t,i)=>{
|
||||
const fly=(u,back)=>{
|
||||
for(let j=12;j>0;j--){const v=u-j*.012;if((sin(T*v)<0)!=back)continue;const[x,y]=F(v);c.lineWidth=3;c.beginPath();c.arc(x,y,3.2,0,T);c.fill();c.stroke()}
|
||||
if((sin(T*u)<0)!=back)return
|
||||
const[x,y]=F(u),[px,py]=F(u-.004),h=atan2(y-py,x-px),f=i%2
|
||||
c.save();c.translate(x,y);c.rotate(h);c.scale(1.45,1.45)
|
||||
c.lineWidth=3.5;for(const d of[-1,1])c.save(),c.translate(-3,d*5),c.rotate(d*(f?.5:1.1)),c.beginPath(),c.ellipse(-8,0,11,6,0,0,T),c.fill(),c.stroke(),c.restore()
|
||||
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.ellipse(-2,0,11,7.5,0,0,T);c.stroke();c.beginPath();c.arc(10,0,6.5,0,T);c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(-2,0,11,7.5,0,0,T);c.fill();c.beginPath();c.arc(10,0,6.5,0,T);c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(12,d*3.5,3,0,T),c.fill()
|
||||
c.restore();c.fillStyle='#fff';c.strokeStyle='#111';c.lineWidth=7
|
||||
}
|
||||
fly(t,1)
|
||||
c.lineWidth=7
|
||||
c.fillStyle='#ddd';c.beginPath();c.moveTo(64,100);c.lineTo(192,100);c.lineTo(222,138);c.lineTo(34,138);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.moveTo(34,138);c.lineTo(82,138);c.lineTo(94,162);c.lineTo(162,162);c.lineTo(174,138);c.lineTo(222,138);c.lineTo(222,208);c.quadraticCurveTo(222,224,206,224);c.lineTo(50,224);c.quadraticCurveTo(34,224,34,208);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const x of[106,150])c.beginPath(),c.arc(x,188,7,0,PI),c.fill()
|
||||
c.lineWidth=5;for(const x of[106,150])c.beginPath(),c.moveTo(x-10,188),c.lineTo(x+10,188),c.stroke()
|
||||
c.beginPath();c.moveTo(119,206);c.lineTo(137,206);c.stroke()
|
||||
c.fillStyle='#fff';c.lineWidth=7
|
||||
fly(t,0)
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// rounded progress bar: the striped fill eases out to full while its stripes slide, then slips off the end and wraps round to start again
|
||||
const{min,max}=Math
|
||||
export const frames=24,delay=70
|
||||
const io=u=>(u=min(1,max(0,u)),u<.5?2*u*u:1-2*(1-u)**2)
|
||||
export default(c,t)=>{
|
||||
const X=32,W=192,b=X+W*io(t/.7),a=X+W*io((t-.72)/.26)
|
||||
c.beginPath();c.roundRect(18,92,220,72,36);c.fill();c.stroke()
|
||||
if(b-a<1)return
|
||||
c.save();c.beginPath();c.roundRect(32,106,192,44,22);c.clip()
|
||||
c.beginPath();c.roundRect(a,106,b-a,44,22);c.clip()
|
||||
c.fillStyle='#111';c.fillRect(0,0,256,256)
|
||||
c.fillStyle='#888';const o=t*72%24
|
||||
for(let x=-48+o;x<256;x+=24)c.beginPath(),c.moveTo(x,150),c.lineTo(x+12,150),c.lineTo(x+34,106),c.lineTo(x+22,106),c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// sliding puzzle loader: rounded blocks in a 2x2 tray take turns sliding into the one empty slot, so the gap walks round and round
|
||||
const{min,max}=Math
|
||||
export const frames=24,delay=70
|
||||
const S=[[44,44],[132,44],[132,132],[44,132]],io=u=>(u=min(1,max(0,u)),u<.5?2*u*u:1-2*(1-u)**2)
|
||||
export default(c,t)=>{
|
||||
const n=Math.floor(t*4),p=io((t*4%1)/.6),g=(7-n)%4
|
||||
c.beginPath();c.roundRect(28,28,200,200,28);c.fill();c.stroke()
|
||||
c.fillStyle='#ddd';for(const[x,y]of S)c.beginPath(),c.roundRect(x+6,y+6,68,68,14),c.fill()
|
||||
c.fillStyle='#fff'
|
||||
for(let k=0;k<4;k++){
|
||||
if(k==g)continue
|
||||
const m=k==(g+3)%4,[x0,y0]=S[k],[x1,y1]=S[g],x=m?x0+(x1-x0)*p:x0,y=m?y0+(y1-y0)*p:y0
|
||||
c.beginPath();c.roundRect(x,y,80,80,18);c.fill();c.stroke()
|
||||
const dx=m&&p<1?(x1-x0)/88*6:0,dy=m&&p<1?(y1-y0)/88*6:0
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(x+40+d*13+dx,y+38+dy,5,0,2*Math.PI),c.fill()
|
||||
c.fillStyle='#fff'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// three chunky dots hop up one after another in a wave, stretching as they fly and squashing as they land
|
||||
const{sin,cos,PI,max,abs}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
export default(c,t)=>{
|
||||
for(let k=0;k<3;k++){
|
||||
const x=54+k*74,u=((t-k*.13)%1+1)%1,h=u<.5?sin(T*u):0,v=u<.5?abs(sin(2*T*u)):0,q=u>.5&&u<.62?sin(PI*(u-.5)/.12):0
|
||||
const sx=1-.05*v+.16*q,sy=1+.07*v-.18*q,r=31,y=196-80*h
|
||||
c.fillStyle='#bbb';c.beginPath();c.ellipse(x,200,24*(1-.45*h)*sx,5*(1-.4*h),0,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.save();c.translate(x,y);c.scale(sx,sy)
|
||||
c.lineWidth=7/((sx+sy)/2);c.beginPath();c.arc(0,-r,r,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// a little smiling planet while two moons circle it at different speeds along dashed orbit paths
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const O=[[72,38,-.42,2,12],[102,58,.3,1,15]]
|
||||
export default(c,t)=>{
|
||||
const pt=([rx,ry,a],f)=>[128+rx*cos(f)*cos(a)-ry*sin(f)*sin(a),128+rx*cos(f)*sin(a)+ry*sin(f)*cos(a)]
|
||||
const orb=(o,a0,a1)=>{for(const[w,s]of[[9,'#111'],[3.5,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.setLineDash([9,18]);c.beginPath();c.ellipse(128,128,o[0],o[1],o[2],a0,a1);c.stroke()}c.setLineDash([])}
|
||||
const M=O.map(o=>{const f=o[3]*T*t+o[3];return[...pt(o,f),o[4]*(1+.15*sin(f)),sin(f)]})
|
||||
const moon=([x,y,r])=>{c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.arc(x,y,r,0,T);c.fill();c.stroke();c.fillStyle='#ccc';c.beginPath();c.arc(x+r*.3,y-r*.25,r*.28,0,T);c.fill();c.fillStyle='#fff'}
|
||||
for(const o of O)orb(o,PI,T)
|
||||
for(const m of M)if(m[3]<0)moon(m)
|
||||
const b=3*sin(T*t*2)
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.beginPath();c.arc(128,128+b,40,0,T);c.fill()
|
||||
c.save();c.clip();c.fillStyle='#ddd';c.beginPath();c.ellipse(128,152+b,52,10,-.12,0,T);c.fill();c.restore()
|
||||
c.beginPath();c.arc(128,128+b,40,0,T);c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*12,122+b,4.5,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(128,130+b,7,.15*PI,.85*PI);c.stroke();c.fillStyle='#fff'
|
||||
for(const o of O)orb(o,0,PI)
|
||||
for(const m of M)if(m[3]>=0)moon(m)
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// a dot sends out radar ripple rings that grow wider and thinner until they fade away
|
||||
const{cos,PI}=Math,T=2*PI
|
||||
export const frames=15,delay=80
|
||||
export default(c,t)=>{
|
||||
for(let k=0;k<3;k++){
|
||||
const p=(t+k/3)%1,r=28+88*p
|
||||
c.lineWidth=16*(1-p)**.7;c.strokeStyle='#999';c.beginPath();c.arc(128,128,r,0,T);c.stroke()
|
||||
}
|
||||
const s=1+.08*cos(T*3*t)
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.beginPath();c.arc(128,128,30*s,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(128,128,13*s,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// material style spinner: one thick arc spins round, stretching long and then shrinking short as it goes
|
||||
const{PI,min,max,floor}=Math,T=2*PI
|
||||
export const frames=30,delay=50
|
||||
const e=u=>(u=min(1,max(0,u)),u<.5?4*u**3:1-4*(1-u)**3)
|
||||
export default(c,t)=>{
|
||||
const q=t*2%1,G=1.5*PI,o=T*t*1.5+floor(t*2)*G-PI/2,a=o+G*e(q*2-1),b=o+.6+G*e(q*2)
|
||||
for(const[w,s]of[[42,'#111'],[28,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(128,128,86,a,b),c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// skeleton placeholder card: gray avatar, text lines and image box with a soft shimmer band sweeping across them
|
||||
const T=2*Math.PI
|
||||
export const frames=20,delay=70
|
||||
export default(c,t)=>{
|
||||
c.beginPath();c.roundRect(22,22,212,212,22);c.fill();c.stroke()
|
||||
const x=-70+t*400,g=c.createLinearGradient(x-56,150,x+56,106)
|
||||
for(const[o,s]of[[0,'#d6d6d6'],[.5,'#f4f4f4'],[1,'#d6d6d6']])g.addColorStop(o,s)
|
||||
c.fillStyle=g;c.beginPath();c.arc(68,68,24,0,T)
|
||||
for(const[x,y,w]of[[104,52,104],[104,74,70],[42,188,172],[42,208,116]])c.roundRect(x,y,w,13,6.5)
|
||||
c.roundRect(42,106,172,70,12);c.fill()
|
||||
c.fillStyle='#c4c4c4';c.beginPath();c.moveTo(96,166);c.lineTo(122,132);c.lineTo(140,152);c.lineTo(152,140);c.lineTo(172,166);c.fill()
|
||||
c.beginPath();c.arc(170,128,9,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// a ring wrench cranks a hex bolt a sixth of a turn and ratchets back for another go, while a big gear turns behind them
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
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 gear=(c,x,y,n,R,th)=>{
|
||||
const p=T/n,ri=R-10,ro=R+9
|
||||
c.beginPath();for(let k=0;k<n;k++){const a=th+k*p;for(const[f,r]of[[-.5,ri],[-.34,ri],[-.22,ro],[.22,ro],[.34,ri]])c.lineTo(x+cos(a+f*p)*r,y+sin(a+f*p)*r)}
|
||||
c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(x,y,R-22,0,T);c.stroke()
|
||||
for(let k=0;k<5;k++){const a=th+k*T/5;c.beginPath();c.arc(x+cos(a)*(R-38),y+sin(a)*(R-38),7,0,T);c.stroke()}
|
||||
c.lineWidth=7;c.beginPath();c.arc(x,y,11,0,T);c.stroke()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const p=ease(t/.5),q=ease((t-.6)/.32),a=-.55+(p-q)*PI/3,b=p*PI/3,X=112,Y=160
|
||||
gear(c,82,92,10,54,-t*T/5)
|
||||
if(p>.15&&p<.95)for(const r of[128,110])ln(c,11,()=>c.arc(X,Y,r,a-.42,a-.16))
|
||||
c.save();c.translate(X,Y);c.rotate(a)
|
||||
const sh=()=>{c.beginPath();c.roundRect(20,-15,104,30,15);c.moveTo(38,0);c.arc(0,0,38,0,T)}
|
||||
c.lineWidth=14;sh();c.stroke();sh();c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.roundRect(52,-5,52,10,5);c.stroke()
|
||||
c.lineWidth=6;c.beginPath();c.arc(0,0,27,0,T);c.stroke()
|
||||
c.restore()
|
||||
c.lineWidth=6;c.beginPath();for(let k=0;k<6;k++)c.lineTo(X+cos(b+k*PI/3)*21,Y+sin(b+k*PI/3)*21);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(X,Y,10,0,T);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// a plug gets yanked out of the wall socket with a tiny spark, it dangles sadly while its cord wiggles, then slides back in
|
||||
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-8,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
export default(c,t,i)=>{
|
||||
const u=min(1,max(0,(t-.1)/.1)),d=56*(1-(1-u)**2)-56*ease((t-.78)/.16),out=d>4,w=out?max(0,1-(t-.2)/.5):0
|
||||
const dy=out?5*sin(T*t*3)*w:0,a=out?.07*sin(T*t*3+1)*w:0,A=2+9*w
|
||||
ln(c,18,()=>{
|
||||
const x0=168+d,y0=128+dy
|
||||
c.moveTo(x0,y0)
|
||||
for(let k=1;k<=24;k++){
|
||||
const v=k/24,m=1-v,bx=m**3*x0+3*m*m*v*(x0+56)+3*m*v*v*230+v**3*202,by=m**3*y0+3*m*m*v*y0+3*m*v*v*200+v**3*244
|
||||
c.lineTo(bx+A*sin(v*12-T*t*4)*v*m*4,by)
|
||||
}
|
||||
})
|
||||
c.beginPath();c.roundRect(12,14,26,232,8);c.fill();c.stroke()
|
||||
c.save();c.translate(116+d,128+dy);c.rotate(a)
|
||||
for(const y of[-18,18])c.beginPath(),c.roundRect(-58,y-5,30,10,3),c.fill(),c.stroke()
|
||||
c.beginPath();c.roundRect(48,-16,16,32,6);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(-30,-38,80,76,18);c.fill();c.stroke()
|
||||
c.fillStyle='#111'
|
||||
if(out){c.lineWidth=5;for(const x of[-6,26])c.beginPath(),c.moveTo(x-6,-12),c.lineTo(x+6,-6),c.moveTo(x-6,-6),c.lineTo(x+6,-12),c.stroke();c.beginPath();c.ellipse(10,14,7,8,0,0,T);c.fill()}
|
||||
else{for(const x of[-6,26])c.beginPath(),c.arc(x,-8,5.5,0,T),c.fill();c.lineWidth=5;c.beginPath();c.arc(10,6,10,.15*PI,.85*PI);c.stroke()}
|
||||
c.restore();c.fillStyle='#fff';c.lineWidth=7
|
||||
c.beginPath();c.roundRect(32,70,58,116,14);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const y of[110,146])c.beginPath(),c.roundRect(76,y-7,14,14,3),c.fill()
|
||||
c.fillStyle='#fff'
|
||||
if(t>.1&&t<.24){
|
||||
const s=1-(t-.1)/.14
|
||||
for(const a of[-2.3,-1.57,-.84,.84,1.57,2.3])ln(c,11,()=>{c.moveTo(98+cos(a)*16,128+sin(a)*16);c.lineTo(98+cos(a)*(16+18*s),128+sin(a)*(16+18*s))})
|
||||
c.lineWidth=5;c.beginPath();for(let k=0;k<8;k++){const r=k%2?5:13*s+4;c.lineTo(98+cos(k*PI/4)*r,128+sin(k*PI/4)*r)};c.closePath();c.fill();c.stroke()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// wifi arcs flicker out one by one from the outside in, a big X pops up and shakes, then the arcs flicker back on
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=28,delay=70
|
||||
const back=u=>(u=min(1,max(0,u)),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||
export default(c,t,i)=>{
|
||||
const R=[50,94,138],O=[9,6,3],N=[20,22,24]
|
||||
for(let k=2;k>=0;k--){
|
||||
const o=O[k],n=N[k],on=i<o||i==o+1||i==n||i>=n+2
|
||||
if(on)for(const[w,s]of[[32,'#111'],[18,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(128,206,R[k],-PI*.75,-PI*.25),c.stroke()
|
||||
else{c.setLineDash([1,15]);for(const[w,s]of[[11,'#111'],[4,'#bbb']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(128,206,R[k],-PI*.75,-PI*.25),c.stroke();c.setLineDash([])}
|
||||
}
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.arc(128,206,20,0,T);c.fill();c.stroke()
|
||||
if(i>=12&&i<20){
|
||||
const s=i<19?back((i-11)/3):.45,r=i>13&&i<19?(i%2?.14:-.14):0
|
||||
c.save();c.translate(128,112);c.rotate(r);c.scale(s,s)
|
||||
for(const[w,k]of[[40,'#111'],[24,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(-36,-36),c.lineTo(36,36),c.moveTo(36,-36),c.lineTo(-36,36),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// a credit card pops in and swipes down the side slot of a card terminal, the screen thinks, then a check pops up with a beep
|
||||
const{sin,cos,PI,min,max,hypot}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const cl=u=>min(1,max(0,u)),ease=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),back=u=>(u=cl(u),1+3*(u-1)**3+2*(u-1)**2)
|
||||
const L=hypot(11,11)+hypot(24,26)
|
||||
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 sw=ease((t-.12)/.2),cy=72+96*sw,cs=back(t/.1)*(1-ease((t-.8)/.08)),ck=cl((t-.42)/.12),v=sin(cl((t-.12)/.2)*PI)
|
||||
c.beginPath();c.roundRect(112,56,104,180,18);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.roundRect(126,72,76,60,9);c.fill()
|
||||
c.fillStyle='#fff';c.lineWidth=4
|
||||
for(let r=0;r<3;r++)for(let k=0;k<3;k++)c.beginPath(),c.arc(140+k*24,156+r*24,8,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7
|
||||
if(ck>0&&t<.94){
|
||||
const s=t>.88?1-(t-.88)/.06:1;c.save();c.translate(164,102);c.scale(s,s)
|
||||
c.strokeStyle='#fff';c.lineWidth=10;c.setLineDash([L*ck,999]);c.beginPath();c.moveTo(-17,0);c.lineTo(-6,11);c.lineTo(18,-15);c.stroke();c.restore()
|
||||
}else for(let k=0;k<3;k++){
|
||||
const j=t>.12&&t<.42?max(0,sin(T*(t*5-k*.25))):0
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(146+k*18,104-9*j,5,0,T);c.fill()
|
||||
}
|
||||
c.fillStyle='#fff'
|
||||
if(ck>.5&&t<.66)for(const a of[-1.65,-.95,-.25])D(()=>{c.moveTo(210+cos(a)*20,60+sin(a)*20);c.lineTo(210+cos(a)*32,60+sin(a)*32)},11,4)
|
||||
if(cs>.01){
|
||||
if(v>.2)for(const x of[50,70,90])D(()=>{c.moveTo(x,cy-58-6*v);c.lineTo(x,max(12,cy-58-40*v))},11,4)
|
||||
c.save();c.translate(70,cy);c.scale(cs,cs)
|
||||
c.beginPath();c.roundRect(-34,-52,68,104,10);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.fillRect(14,-48,12,96)
|
||||
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.roundRect(-24,-34,22,26,5);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(-24,-21);c.lineTo(-2,-21);c.moveTo(-13,-34);c.lineTo(-13,-8);c.stroke()
|
||||
c.lineWidth=6;for(const y of[12,30])c.beginPath(),c.moveTo(-18,y),c.lineTo(-18,y+10),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
c.lineWidth=7;c.beginPath();c.roundRect(98,36,22,184,10);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(109,48);c.lineTo(109,208);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// a floppy disk squishes as it saves, then a check badge pops onto its corner, the check draws itself and the disk smiles
|
||||
const{sin,cos,PI,min,max,hypot}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const cl=u=>min(1,max(0,u)),bk=u=>(u=cl(u),1+2.7*(u-1)**3+1.7*(u-1)**2)
|
||||
const P=[[-17,1],[-5,13],[18,-12]],LL=hypot(12,12)+hypot(23,25)
|
||||
export default(c,t)=>{
|
||||
const q=sin(PI*cl(t/.16)),s=t<.86?bk((t-.16)/.14):1-cl((t-.86)/.12)**2,p=cl((t-.26)/.16),b=(t-.42)/.18,hp=t>.36&&t<.92
|
||||
c.save();c.translate(116,198);c.scale(1+.07*q,1-.09*q);c.translate(-116,-198)
|
||||
c.beginPath();c.moveTo(30,46);c.quadraticCurveTo(30,30,46,30);c.lineTo(174,30);c.lineTo(202,58);c.lineTo(202,182);c.quadraticCurveTo(202,198,186,198);c.lineTo(46,198);c.quadraticCurveTo(30,198,30,182);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#ddd';c.beginPath();c.roundRect(66,30,100,58,[0,0,8,8]);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.roundRect(132,42,18,34,3);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.roundRect(56,112,120,86,[12,12,0,0]);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.lineWidth=5
|
||||
if(hp)for(const d of[-1,1])c.beginPath(),c.arc(116+d*20,152,7,PI*1.1,PI*1.9),c.stroke()
|
||||
else for(const d of[-1,1])c.beginPath(),c.arc(116+d*20,148,6,0,T),c.fill()
|
||||
c.beginPath();c.arc(116,160,hp?14:9,.15*PI,.85*PI);c.stroke()
|
||||
c.restore()
|
||||
c.fillStyle='#fff';c.strokeStyle='#111'
|
||||
if(b>0&&b<1)for(let k=0;k<8;k++){const a=k*T/8+PI/8,r1=44+12*b,r2=r1+12*(1-b);for(const[w,st]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(190+cos(a)*r1,190+sin(a)*r1),c.lineTo(190+cos(a)*r2,190+sin(a)*r2),c.stroke()}
|
||||
if(s>.01){
|
||||
c.strokeStyle='#111';c.save();c.translate(190,190);c.scale(s,s);c.lineWidth=7/s
|
||||
c.beginPath();c.arc(0,0,36,0,T);c.fill();c.stroke()
|
||||
if(p>0){c.lineWidth=11;c.setLineDash([LL*p,999]);c.beginPath();for(const[x,y]of P)c.lineTo(x,y);c.stroke()}
|
||||
c.restore()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// binoculars with big worried eyes in the lenses sweep left and right looking for something, find nothing, and break a sweat
|
||||
const{sin,PI,min,max}=Math,T=2*PI
|
||||
export const frames=20,delay=90
|
||||
const cl=u=>min(1,max(0,u))
|
||||
export default(c,t)=>{
|
||||
const s=sin(T*t),x=128+27*s,y=130,lk=sin(T*t+.5),S=1.04
|
||||
c.save();c.translate(x,y);c.rotate(.1*s);c.scale(S,S);c.lineWidth=7/S
|
||||
c.beginPath();c.roundRect(-24,-30,48,40,9);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(0,-40,11,0,T);c.fill();c.stroke()
|
||||
for(const d of[-1,1]){
|
||||
const cx=d*44
|
||||
c.beginPath();c.roundRect(cx-17,-66,34,24,7);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(cx-34,-48,68,100,30);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(cx,18,28,0,T);c.fill();c.stroke()
|
||||
const px=cx+9*lk,py=20
|
||||
c.fillStyle='#111';c.beginPath();c.arc(px,py,13,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(px-4,py-5,4.5,0,T);c.fill()
|
||||
c.lineWidth=5/S;c.beginPath();c.moveTo(cx-18,-16-d*3);c.lineTo(cx+18,-16+d*3);c.stroke();c.lineWidth=7/S
|
||||
}
|
||||
c.restore()
|
||||
const g=cl((t-.12)/.1)*(1-cl((t-.74)/.1)),dy=50*cl((t-.22)/.52)**1.4
|
||||
if(g>0){
|
||||
c.save();c.translate(x+64+4*s,y-62+dy*.8);c.scale(g,g);c.lineWidth=6
|
||||
c.beginPath();c.moveTo(0,-20);c.bezierCurveTo(4,-8,14,0,14,9);c.arc(0,9,14,0,PI);c.bezierCurveTo(-14,0,-4,-8,0,-20);c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// a paper plane swoops in, flies a loop-the-loop and zooms off the other side, leaving a dashed trail behind it
|
||||
const{sin,cos,PI,atan2,min,max,hypot}=Math,T=2*PI
|
||||
export const frames=24,delay=60
|
||||
const sm=u=>(u=min(1,max(0,u)),u*u*(3-2*u))
|
||||
const P=s=>{const w=sm((s-.28)/.38);return[-52+360*s-56*sin(T*w),176-56*(1-cos(T*w))-22*sin(PI*min(1,max(0,s)))]}
|
||||
const Q=[];{let l=0,q=P(-1);for(let s=-1;s<=2.001;s+=.004){const p=P(s);l+=hypot(p[0]-q[0],p[1]-q[1]);Q.push([s,...p,l]);q=p}}
|
||||
const L=.46
|
||||
const trail=(c,h)=>{
|
||||
const D=[];let cur=null
|
||||
for(const[s,x,y,l]of Q){if(s<h-L||s>h-.06){cur=null;continue}if(l%30<17){if(!cur)D.push(cur=[]);cur.push([x,y,s])}else cur=null}
|
||||
for(const k of[0,1])for(const d of D){const f=(d[0][2]-h+L)/L;c.lineWidth=k?max(0,9*f-1):4+9*f;c.strokeStyle=k?'#fff':'#111';c.beginPath();for(const[x,y]of d)c.lineTo(x,y);c.stroke()}
|
||||
}
|
||||
const plane=(c,h)=>{
|
||||
const[x,y]=P(h),[a,b]=P(h-.01),[e,f]=P(h+.01)
|
||||
c.save();c.translate(x,y);c.rotate(atan2(f-b,e-a));c.scale(1.4,1.4);c.strokeStyle='#111';c.lineWidth=5
|
||||
c.fillStyle='#ddd';c.beginPath();c.moveTo(32,0);c.lineTo(-14,4);c.lineTo(-22,18);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.moveTo(32,0);c.lineTo(-30,-20);c.lineTo(-14,4);c.closePath();c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
for(const h of[t,t+1])trail(c,h)
|
||||
for(const h of[t,t+1])plane(c,h)
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// a phone with no signal, its empty bars light up one by one as it searches and then blink, while its little face looks round sadly
|
||||
const{sin,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
export default(c,t,i)=>{
|
||||
c.beginPath();c.roundRect(58,10,140,236,28);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.roundRect(72,38,112,176,12);c.stroke()
|
||||
c.lineWidth=6;c.beginPath();c.moveTo(112,24);c.lineTo(144,24);c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128,230,7,0,T);c.stroke()
|
||||
const scan=i<8?i>>1:-1,dim=i>=8&&i%4>1
|
||||
for(let k=0;k<4;k++){
|
||||
const h=18+16*k,x=82+k*24
|
||||
c.fillStyle=k==scan?'#bbb':'#fff';c.strokeStyle=dim?'#bbb':'#111';c.lineWidth=5
|
||||
c.beginPath();c.roundRect(x,126-h,18,h,4);c.fill();c.stroke()
|
||||
}
|
||||
c.fillStyle='#111';c.strokeStyle='#111'
|
||||
const e=i<8?(scan-1.5)*3:0
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(128+d*16+e,160,6,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128+e*.5,192,12,PI*1.15,PI*1.85);c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(100+e,151);c.lineTo(112+e,145);c.moveTo(156+e,151);c.lineTo(144+e,145);c.stroke()
|
||||
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.moveTo(164,140+(i%8));c.bezierCurveTo(158,152+(i%8),160,160+(i%8),166,160+(i%8));c.bezierCurveTo(172,160+(i%8),174,152+(i%8),164,140+(i%8));c.fill();c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// a party popper shakes, then bursts with a bang and confetti pieces and streamers flutter down, spinning as they fall
|
||||
const{sin,cos,PI,min,max,exp}=Math,T=2*PI
|
||||
export const frames=28,delay=70
|
||||
let z=11;const R=()=>(z=z*16807%2147483647)/2147483647
|
||||
const C=[...Array(14)].map((_,k)=>[-PI/4+(R()-.5)*1.7,90+R()*120,k%4,R()<.3?'#bbb':'#fff',R()*T,1+R()*2,R()*T,.7+R()*.6])
|
||||
const t0=.12
|
||||
export default(c,t)=>{
|
||||
const s=t-t0,mx=110,my=150
|
||||
if(s>0){
|
||||
const sc=min(1,(1-t)/.07),fall=u=>320*max(0,u-.12)**1.5
|
||||
for(const[a,d,k,f,r0,sp,ph,fz]of C){
|
||||
const e=1-exp(-11*s),x=mx+cos(a)*d*e+14*sin(T*s*2*fz+ph)*min(1,s*4),y=my+sin(a)*d*e+fall(s)*fz
|
||||
c.save();c.translate(x,y);c.rotate(r0+s*sp*T);c.scale(cos(T*s*3*fz+ph)*sc,sc);c.beginPath()
|
||||
if(k==0)c.rect(-11,-7,22,14);else if(k==1)c.arc(0,0,9,0,T);else if(k==2)c.moveTo(0,-11),c.lineTo(10,7),c.lineTo(-10,7),c.closePath();else c.ellipse(0,0,13,6,0,0,T)
|
||||
c.restore();c.lineWidth=5;c.fillStyle=f;c.fill();c.stroke()
|
||||
}
|
||||
c.fillStyle='#fff'
|
||||
for(const[a,d,o]of[[-1.15,120,0],[-.5,130,2]]){
|
||||
const e=1-exp(-9*s);for(const[w,st]of[[10,'#111'],[4,'#fff']]){c.lineWidth=w*sc;c.strokeStyle=st;c.beginPath()
|
||||
for(let u=0;u<=1;u+=.05){const L=d*e*(.35+.65*u),n=7*sin(u*12+s*20+o)*min(1,s*6);c.lineTo(mx+cos(a)*L-sin(a)*n,my+sin(a)*L+cos(a)*n+fall(s)*(1.1-.4*u)+40*s*u*u)}c.stroke()}
|
||||
}
|
||||
c.strokeStyle='#111'
|
||||
if(s<.12){const b=s/.12;for(let k=0;k<7;k++){const a=-PI/4+(k-3)*.42,r1=24+40*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(mx+cos(a)*r1,my+sin(a)*r1),c.lineTo(mx+cos(a)*r2,my+sin(a)*r2),c.stroke()}}
|
||||
}
|
||||
const sh=t<t0?.08*sin(T*t*14)*t/t0:t>.9?.05*sin(T*t*20)*(t-.9)/.1:0,rc=s>0&&s<.15?sin(PI*s/.15):0
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.save();c.translate(42-8*rc,222+8*rc);c.rotate(PI/4+sh)
|
||||
const cone=()=>{c.beginPath();c.moveTo(-9,6);c.lineTo(-38,-92);c.lineTo(38,-92);c.lineTo(9,6);c.quadraticCurveTo(0,11,-9,6)}
|
||||
cone();c.fill();c.save();cone();c.clip();c.fillStyle='#111'
|
||||
for(const v of[-70,-36])c.beginPath(),c.moveTo(-40,v),c.lineTo(40,v-20),c.lineTo(40,v-6),c.lineTo(-40,v+14),c.fill()
|
||||
c.restore();cone();c.stroke()
|
||||
c.beginPath();c.ellipse(0,-92,38,12,0,0,T);c.fill();c.stroke()
|
||||
if(s<0||s>.5){c.fillStyle='#111';c.beginPath();c.ellipse(0,-92,27,6,0,0,T);c.fill()}
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// a rubber stamp winds up, slams down on a sheet of paper and bounces back up leaving a check mark imprint, then the sheet slides away for a fresh one
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=28,delay=70
|
||||
const cl=u=>min(1,max(0,u)),io=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),bk=u=>(u=cl(u),1+2.4*(u-1)**3+1.4*(u-1)**2)
|
||||
const paper=(c,x)=>{c.beginPath();c.moveTo(62+x,162);c.lineTo(194+x,162);c.lineTo(224+x,230);c.lineTo(32+x,230);c.closePath();c.fill();c.stroke()}
|
||||
const ink=(c,x)=>{c.save();c.translate(128+x,196);c.scale(1,.42);c.lineWidth=10;c.beginPath();c.arc(0,0,44,0,T);c.stroke();c.lineWidth=14;c.beginPath();c.moveTo(-20,0);c.lineTo(-6,16);c.lineTo(22,-16);c.stroke();c.restore()}
|
||||
export default(c,t)=>{
|
||||
const sl=-264*io((t-.74)/.22),q=sin(PI*cl((t-.31)/.11))
|
||||
const y=t<.24?124-10*io((t-.06)/.18):t<.31?114+82*cl((t-.24)/.07)**2:t<.42?196:196-72*bk((t-.42)/.16)
|
||||
paper(c,sl);paper(c,sl+264)
|
||||
const h=(y-124)/72
|
||||
if(t<.31||t>.42&&t<.74||t>.96){c.fillStyle='#ccc';c.beginPath();c.ellipse(128,196,30+22*h,9+4*h,0,0,T);c.fill();c.fillStyle='#fff'}
|
||||
if(t>.31)ink(c,sl)
|
||||
if(t>.6&&t<.74){const p=(t-.6)/.14;c.lineWidth=5;for(const[x,yy,r]of[[52,146,12],[206,154,10]]){const s=sin(PI*p)*r;c.beginPath();c.moveTo(x,yy-s*2);c.quadraticCurveTo(x,yy,x+s*2,yy);c.quadraticCurveTo(x,yy,x,yy+s*2);c.quadraticCurveTo(x,yy,x-s*2,yy);c.quadraticCurveTo(x,yy,x,yy-s*2);c.fill();c.stroke()}}
|
||||
if(q>.01)for(const d of[-1,1])for(const a of[-.5,0,.5]){const r1=72+14*q,r2=r1+16*q;for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(128+d*r1*cos(a),188-r1*.5*sin(a+.4)),c.lineTo(128+d*r2*cos(a),188-r2*.5*sin(a+.4)),c.stroke()}
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.save();c.translate(128,y);c.scale(1+.08*q,1-.12*q)
|
||||
c.fillStyle='#888';c.beginPath();c.roundRect(-48,-12,96,12,3);c.fill();c.stroke();c.fillStyle='#fff'
|
||||
c.beginPath();c.roundRect(-58,-38,116,28,9);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(-14,-62,28,26,4);c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(0,-82,31,19,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(0,-82,14,PI*1.15,PI*1.5);c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// two curved arrows chase each other round and round a little face that watches them go
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=60
|
||||
export default(c,t)=>{
|
||||
const a0=PI*t+.2*sin(T*t),R=80,S=2.15
|
||||
for(const[w,k]of[[34,'#111'],[20,'#fff']])for(const o of[0,PI]){
|
||||
const a=a0+o,e=a+S,px=128+R*cos(e),py=128+R*sin(e),tx=-sin(e),ty=cos(e),nx=cos(e),ny=sin(e)
|
||||
c.lineWidth=w;c.strokeStyle=k;c.beginPath();c.arc(128,128,R,a,e);c.stroke()
|
||||
c.fillStyle=k;c.lineWidth=w>30?14:0;c.beginPath();c.moveTo(px+nx*28,py+ny*28);c.lineTo(px+tx*34,py+ty*34);c.lineTo(px-nx*28,py-ny*28);c.closePath();c.fill();if(w>30)c.stroke()
|
||||
}
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
c.beginPath();c.arc(128,128,38,0,T);c.fill();c.stroke()
|
||||
const ex=4*sin(T*t*2)
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*13+ex,121,6,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128+ex*.5,132,9,PI*.15,PI*.85);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// a folded thank-you card swings open, a smiling heart pops out and floats up, bursts into lines, and the card closes again
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const cl=u=>min(1,max(0,u)),ease=u=>(u=cl(u),u<.5?2*u*u:1-2*(1-u)**2),back=u=>(u=cl(u),1+3*(u-1)**3+2*(u-1)**2)
|
||||
const heart=(c,r)=>{c.beginPath();c.moveTo(0,r);c.bezierCurveTo(-r*1.7,-r*.1,-r*.9,-r*1.45,0,-r*.6);c.bezierCurveTo(r*.9,-r*1.45,r*1.7,-r*.1,0,r);c.closePath()}
|
||||
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 o=ease((t-.04)/.2)-ease((t-.84)/.14),th=o*PI,hx=76+52*o,Y=102,H=132,W=104
|
||||
c.beginPath();c.roundRect(hx,Y,W,H,6);c.fill();c.stroke()
|
||||
c.lineWidth=8;c.strokeStyle='#bbb';for(const[y,l]of[[Y+76,56],[Y+94,70],[Y+112,44]])c.beginPath(),c.moveTo(hx+16,y),c.lineTo(hx+16+l,y),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
const k=cos(th),lift=.1*sin(th)
|
||||
c.save();c.transform(k,-lift,0,1,hx,0);c.beginPath();c.roundRect(0,Y,W,H,6);c.fill();c.lineWidth=7;c.stroke()
|
||||
if(k>0){
|
||||
c.save();c.translate(W/2,Y+54);c.lineWidth=6;heart(c,22);c.stroke();c.restore()
|
||||
c.lineWidth=7;c.strokeStyle='#bbb';for(const[y,l]of[[Y+96,48],[Y+111,32]])c.beginPath(),c.moveTo(W/2-l/2,y),c.lineTo(W/2+l/2,y),c.stroke()
|
||||
}else{c.translate(W/2,Y+H-30);c.scale(-1,1);c.lineWidth=5;c.strokeStyle='#bbb';heart(c,10);c.stroke();c.beginPath();c.moveTo(-36,26);c.lineTo(36,26);c.stroke()}
|
||||
c.restore()
|
||||
const P=u=>[128+14*sin(u*T),170-108*u],u=min((t-.26)/.54,.96),b=cl((t-.78)/.08),[x,y]=P(u)
|
||||
if(u>0&&b<1){
|
||||
const s=back((t-.26)/.08)*(1-b)
|
||||
c.save();c.translate(x,y);c.rotate(.16*sin(u*T+1));c.scale(s,s);c.lineWidth=7/max(s,.2)
|
||||
heart(c,32);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*11,-4,4.5,0,T),c.fill()
|
||||
c.lineWidth=4.5/max(s,.2);c.beginPath();c.arc(0,4,7,.15*PI,.85*PI);c.stroke();c.restore()
|
||||
}
|
||||
if(b>0&&b<1)for(let i=0;i<8;i++){const a=i*T/8,r1=22+26*b,r2=r1+14*(1-b);D(()=>{c.moveTo(x+cos(a)*r1,y+sin(a)*r1);c.lineTo(x+cos(a)*r2,y+sin(a)*r2)},11,4)}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// a stopwatch hand ticks round to zero as the time left shrinks away, then it rings and shakes, and winds back for another go
|
||||
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'}
|
||||
export default(c,t,i)=>{
|
||||
const X=128,Y=146,ring=t>=.5&&t<.8,f=T*(.25+.75*(min(1,t/.5)-ease((t-.8)/.18)))-PI/2
|
||||
if(ring)for(const d of[-1,1])for(const a of[-.5,0,.5])ln(c,11,()=>{const b=-PI/2+d*(.72+a*.5),r=i%2?4:0;c.moveTo(X+cos(b)*(106+r),Y+sin(b)*(106+r));c.lineTo(X+cos(b)*(122+r),Y+sin(b)*(122+r))})
|
||||
c.translate(X,Y);if(ring)c.rotate(i%2?.09:-.09),c.translate(i%2?2:-2,0);c.translate(-X,-Y)
|
||||
c.save();c.translate(X,Y);c.rotate(PI/4);c.beginPath();c.roundRect(-9,-100,18,22,5);c.fill();c.stroke();c.restore()
|
||||
c.beginPath();c.roundRect(X-10,48,20,24,4);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(X-28,ring&&i%2?34:28,56,20,8);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(X,Y,86,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#ddd';c.beginPath();c.moveTo(X,Y);c.arc(X,Y,64,f,PI*1.5);c.closePath();c.fill();c.fillStyle='#fff'
|
||||
c.lineWidth=5;c.beginPath();c.arc(X,Y,72,0,T);c.stroke()
|
||||
for(let k=0;k<12;k++){const a=k*T/12,r=k%3?62:56;c.lineWidth=k%3?4:6;c.beginPath();c.moveTo(X+cos(a)*r,Y+sin(a)*r);c.lineTo(X+cos(a)*68,Y+sin(a)*68);c.stroke()}
|
||||
c.lineWidth=8;c.beginPath();c.moveTo(X-cos(f)*12,Y-sin(f)*12);c.lineTo(X+cos(f)*60,Y+sin(f)*60);c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(X,Y,9,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// chat speech bubble gently bobbing while three typing dots pulse up and darken one after another
|
||||
const{sin,PI,max}=Math,T=2*PI
|
||||
export const frames=18,delay=70
|
||||
export default(c,t)=>{
|
||||
c.translate(0,3*sin(T*t))
|
||||
const B=()=>{c.beginPath();c.roundRect(22,56,212,128,44)},K=()=>{c.beginPath();c.moveTo(58,168);c.quadraticCurveTo(58,204,30,218);c.quadraticCurveTo(84,214,100,176);c.closePath()}
|
||||
c.lineWidth=14;B();c.stroke();K();c.stroke();B();c.fill();K();c.fill()
|
||||
for(let k=0;k<3;k++){
|
||||
const u=((t-k*.16)%1+1)%1,p=u<.42?sin(PI*u/.42):0
|
||||
c.fillStyle=p>.6?'#111':p>.25?'#555':'#999'
|
||||
c.beginPath();c.arc(84+k*44,120-12*p,14+4*p,0,T);c.fill()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// arrows pop up, crouch and shoot one after another into a happy cloud, which puffs up each time one zips inside
|
||||
const{sin,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=60
|
||||
const back=u=>(u=min(1,max(0,u)),1+2.7*(u-1)**3+1.7*(u-1)**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'}
|
||||
export default(c,t)=>{
|
||||
const u=t*2%1,s=1.1*back(u/.14),q=max(0,(u-.3)/.2),k=u>.14&&u<.3?sin(PI*(u-.14)/.16):0,y=196+6*k-110*q*q,pf=u>.42&&u<.82?sin(PI*(u-.42)/.4):0
|
||||
if(q<1){
|
||||
if(q>0)for(const x of[-30,0,30])ln(c,11,()=>{c.moveTo(128+x,y+(x?16:58));c.lineTo(128+x,y+(x?16:58)+56*q)})
|
||||
c.save();c.translate(128,y+40);c.scale(s*(1+.1*k),s*(1-.14*k));c.translate(0,-40)
|
||||
c.beginPath();c.moveTo(0,-40);c.lineTo(36,-2);c.lineTo(15,-2);c.lineTo(15,38);c.lineTo(-15,38);c.lineTo(-15,-2);c.lineTo(-36,-2);c.closePath();c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
if(pf>.3)for(const d of[-1,1])for(const[y,q]of[[66,-10],[100,0]])ln(c,11,()=>{c.moveTo(128+d*(102+6*pf),y);c.lineTo(128+d*(116+6*pf),y+q)})
|
||||
c.translate(128,110);c.scale(1+.08*pf,1+.06*pf);c.translate(-128,-110)
|
||||
const P=[[80,96,38],[128,72,50],[178,94,40]],base=()=>c.roundRect(42,92,172,56,28)
|
||||
c.lineWidth=14;for(const[x,yy,r]of P)c.beginPath(),c.arc(x,yy,r,0,T),c.stroke()
|
||||
c.beginPath();base();c.stroke()
|
||||
for(const[x,yy,r]of P)c.beginPath(),c.arc(x,yy,r,0,T),c.fill()
|
||||
c.beginPath();base();c.fill()
|
||||
c.lineWidth=6
|
||||
if(pf>.3)for(const x of[106,150])c.beginPath(),c.arc(x,114,8,PI*1.15,PI*1.85),c.stroke()
|
||||
else{c.fillStyle='#111';for(const x of[106,150])c.beginPath(),c.arc(x,110,6,0,T),c.fill()}
|
||||
c.beginPath();c.arc(128,120,10,PI*.15,PI*.85);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// scalloped seal badge with a big check, gently wobbling, a shine sweeps across it and little sparkles twinkle
|
||||
const{sin,cos,PI,abs,min,max}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const cl=u=>min(1,max(0,u))
|
||||
const star=(c,x,y,r)=>{c.beginPath();for(let k=0;k<8;k++){const a=k*PI/4,q=k%2?r*.42:r;c.lineTo(x+cos(a)*q,y+sin(a)*q)}c.closePath();c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const a=.1*sin(T*t),sh=cl((t-.12)/.3)
|
||||
for(const d of[-1,1]){
|
||||
c.save();c.translate(128+d*26,150);c.rotate(d*.32+a*.5)
|
||||
c.beginPath();c.moveTo(-20,0);c.lineTo(-20,82);c.lineTo(0,68);c.lineTo(20,82);c.lineTo(20,0);c.closePath();c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
c.translate(128,110);c.rotate(a)
|
||||
const seal=()=>{c.beginPath();for(let k=0;k<=320;k++){const th=k*T/320,r=80+11*(1-(1-abs(cos(8*th)))**2);c.lineTo(cos(th)*r,sin(th)*r)}c.closePath()}
|
||||
seal();c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(0,0,62,0,T);c.fill()
|
||||
if(sh>0&&sh<1){
|
||||
c.save();c.beginPath();c.arc(0,0,62,0,T);c.clip();c.rotate(.6);c.fillStyle='#666'
|
||||
const x=-110+220*sh;c.fillRect(x-14,-80,22,160);c.fillRect(x+16,-80,8,160);c.restore()
|
||||
}
|
||||
c.strokeStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(0,0,52,0,T);c.stroke()
|
||||
c.lineWidth=20;c.beginPath();c.moveTo(-26,2);c.lineTo(-8,20);c.lineTo(28,-20);c.stroke()
|
||||
c.setTransform(1,0,0,1,0,0);c.strokeStyle='#111';c.fillStyle='#fff';c.lineWidth=5
|
||||
for(const[x,y,o,r]of[[214,40,.42,22],[40,60,.56,18],[222,150,.7,16]]){const g=cl((t-o)/.22),s=sin(g*PI);if(s>0)star(c,x,y,r*s)}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// warning triangle with a big "!" wobbling on its corner, the "!" jiggling along, alert lines flashing on both sides
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t,i)=>{
|
||||
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 a=.1*sin(2*T*t),b=.14*sin(2*T*t-1.2),fl=i%4<2
|
||||
if(fl)for(const d of[-1,1])for(const k of[0,1,2]){const g=-PI/2+d*(.62+k*.3),r=96+(k==1?8:0);D(()=>{c.moveTo(128+cos(g)*r,130+sin(g)*r);c.lineTo(128+cos(g)*(r+20),130+sin(g)*(r+20))},12,5)}
|
||||
c.translate(128,214);c.rotate(a);c.translate(-128,-214)
|
||||
const tri=()=>{c.beginPath();c.moveTo(128,44);c.lineTo(222,206);c.lineTo(34,206);c.closePath()}
|
||||
tri();c.lineWidth=34;c.stroke();c.lineWidth=20;c.strokeStyle='#fff';c.stroke();c.fill()
|
||||
c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.moveTo(128,62);c.lineTo(207,198);c.lineTo(49,198);c.closePath();c.stroke()
|
||||
c.translate(128,188);c.rotate(b);c.lineWidth=24;c.beginPath();c.moveTo(0,-90);c.lineTo(0,-46);c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(0,-12,13,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// an empty wishlist heart drawn as a chunky dashed outline, gently breathing in and out
|
||||
const{sin,cos,PI,hypot}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const P=[...Array(161)].map((_,k)=>{const s=k/160*T;return[16*sin(s)**3,-(13*cos(s)-5*cos(2*s)-2*cos(3*s)-cos(4*s))]})
|
||||
const L=P.reduce((a,p,k)=>k?a+hypot(p[0]-P[k-1][0],p[1]-P[k-1][1]):0,0),D=L/12
|
||||
export default(c,t)=>{
|
||||
const s=6.1*(1+.06*sin(t*T))
|
||||
c.translate(128,114);c.scale(s,s*(1-.02*sin(t*T)))
|
||||
c.setLineDash([D*.46,D*.54]);c.lineDashOffset=D*.73
|
||||
for(const[w,k]of[[22,'#111'],[10,'#fff']]){c.lineWidth=w/s;c.strokeStyle=k;c.beginPath();for(const[x,y]of P)c.lineTo(x,y);c.stroke()}
|
||||
}
|
||||
Reference in New Issue
Block a user