mirror of
https://github.com/direct-img/vibegif.direct-img.link.git
synced 2026-10-29 03:34:51 +00:00
Double the black-and-white section with 50 more stickers
Animals (mouse, sheep, cow, elephant, monkey, lion, sloth, bat, spider, hedgehog, shark, seal, caterpillar, pigeon, koala, squirrel), weather (snowman, tornado, wind, icicle), food (toaster, banana, lemon, cherry, pudding, teapot, hot dog, lollipop, carrot, milk), objects (scissors, padlock, candle, fan, gears, stapler, faucet, trash, tv, cursor) and toys and symbols (yo-yo, spring, Newton's cradle, drum, trumpet, bowling, basketball, skull, question mark, puzzle). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
// banana peel opening flap by flap to show the happy curved fruit inside, then folding shut again in reverse
|
||||
// each flap is a quadratic center line widened along its normal, so it can bend from hugging the fruit to drooping open
|
||||
// flap roots and the peel's top edge aren't outlined while shut, so the closed banana reads as one piece
|
||||
const{sin,PI,min,max,hypot}=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 mix=(a,b,o)=>a.map((v,i)=>v+(b[i]-v)*o)
|
||||
const flap=(c,[P,C,Q],W,o,stem)=>{
|
||||
const pt=s=>[(1-s)**2*P[0]+2*s*(1-s)*C[0]+s*s*Q[0],(1-s)**2*P[1]+2*s*(1-s)*C[1]+s*s*Q[1]]
|
||||
const L=[],R=[]
|
||||
for(let k=0;k<=20;k++){const s=k/20,[x,y]=pt(s),[x2,y2]=pt(min(1,s+.01)),[x0,y0]=pt(max(0,s-.01)),dx=x2-x0,dy=y2-y0,n=hypot(dx,dy)||1,h=W*(1-s)**.6;L.push([x-dy/n*h,y+dx/n*h]);R.push([x+dy/n*h,y-dx/n*h])}
|
||||
if(stem){const[x,y]=Q,[x0,y0]=pt(.95),n=hypot(x-x0,y-y0);c.lineWidth=12;c.beginPath();c.moveTo(x,y);c.lineTo(x+(x-x0)/n*14,y+(y-y0)/n*14);c.stroke();c.lineWidth=4;c.strokeStyle='#fff';c.stroke();c.strokeStyle='#111';c.lineWidth=7}
|
||||
c.beginPath();for(const p of L)c.lineTo(...p);for(const p of R.reverse())c.lineTo(...p);c.fill();c.stroke()
|
||||
if(o>.3)c.lineWidth=4,c.beginPath(),[...Array(17)].forEach((_,k)=>c.lineTo(...pt((k+1)/20))),c.stroke(),c.lineWidth=7
|
||||
}
|
||||
const star=(c,x,y,r)=>{const k=r*.18;c.beginPath();c.moveTo(x,y-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(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
const shut=[[[110,166],[100,100],[132,56]],[[146,166],[156,104],[140,56]],[[127,170],[122,100],[136,58]]]
|
||||
const wide=[[[110,154],[60,116],[44,198]],[[146,154],[198,120],[214,198]],[[127,158],[124,200],[112,236]]]
|
||||
export default(c,t)=>{
|
||||
const o=[0,1,2].map(k=>ease((t-k*.13)/.13)-ease((t-.62-(2-k)*.1)/.1)),open=o[2]>.9
|
||||
c.beginPath();c.moveTo(104,162);c.bezierCurveTo(100,120,108,84,136,58);c.bezierCurveTo(148,84,154,120,152,162);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const x of[120,141])c.beginPath(),c.ellipse(x,110,4.5,6,0,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[119,140])c.beginPath(),c.arc(x,108,1.8,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(130,118,7,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=2.5;for(const x of[112,148])for(const k of[-3,1])c.beginPath(),c.moveTo(x+k-1.5,127),c.lineTo(x+k+1.5,122),c.stroke()
|
||||
c.lineWidth=7;c.fillStyle='#fff'
|
||||
const base=()=>{c.beginPath();c.moveTo(158,146);c.bezierCurveTo(160,186,146,210,124,220);c.quadraticCurveTo(112,224,110,216);c.bezierCurveTo(98,196,94,176,96,146)}
|
||||
for(const k of[0,1])flap(c,[0,1,2].map(i=>mix(shut[k][i],wide[k][i],o[k])),18,o[k])
|
||||
base();c.fill();c.stroke()
|
||||
const m=max(o[0],o[1]);if(m>.05)c.lineWidth=7*min(1,m*3),c.beginPath(),c.moveTo(96,148),c.quadraticCurveTo(127,156,158,148),c.stroke(),c.lineWidth=7
|
||||
c.save();c.translate(114,222);c.rotate(.5);c.beginPath();c.roundRect(-7,-4,14,10,4);c.lineWidth=16;c.strokeStyle='#fff';c.stroke();c.fillStyle='#111';c.fill();c.lineWidth=7;c.strokeStyle='#111';c.stroke();c.restore()
|
||||
c.fillStyle='#fff'
|
||||
flap(c,[0,1,2].map(i=>mix(shut[2][i],wide[2][i],o[2])),16,o[2],1)
|
||||
if(open){c.lineWidth=4;const p=(t-.39)/.23;for(const[x,y,ph]of[[70,70,0],[190,78,.5]]){const r=11*sin(PI*((p*2+ph)%1));if(r>2)star(c,x,y,r)}}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// basketball bouncing: squashes on the floor, stretches as it flies, seams turning as it spins
|
||||
const{PI,abs}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
export default(c,t)=>{
|
||||
const h=116*4*t*(1-t),v=abs(1-2*t),con=t<.03,r=48,k=1-h/170
|
||||
const sx=con?1.2:1-.08*v,sy=con?.8:1+.1*v
|
||||
for(const[l,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(128-46*k,238),c.lineTo(128+46*k,238),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.translate(128,232-h);c.scale(sx,sy);c.translate(0,-r)
|
||||
c.beginPath();c.arc(0,0,r,0,T);c.fill()
|
||||
c.save();c.clip();c.rotate(t*T);c.lineWidth=5;c.beginPath()
|
||||
c.moveTo(-r,0);c.lineTo(r,0);c.moveTo(0,-r);c.lineTo(0,r)
|
||||
for(const d of[-1,1])c.moveTo(d*r*.66,-r),c.quadraticCurveTo(d*r*.08,0,d*r*.66,r)
|
||||
c.stroke();c.restore()
|
||||
c.beginPath();c.arc(0,0,r,0,T);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// bat flapping its wings and bobbing up and down
|
||||
// every dark part gets its white rim in one pass first, so the bat reads as one silhouette on black
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const delay=60
|
||||
export default(c,t)=>{
|
||||
const w=sin(2*T*t),y=118-8*w,E=[[100,-22],[78,18],[52,10],[30,26],[2,14]]
|
||||
const wing=d=>()=>{c.save();c.translate(128+d*14,y);c.scale(d,1);c.rotate(-.45*w);c.moveTo(0,-6);c.quadraticCurveTo(50,-46,...E[0]);for(let i=1;i<5;i++){const[p,q]=[E[i-1],E[i]];c.quadraticCurveTo((p[0]+q[0])/2,(p[1]+q[1])/2-12,...q)}c.closePath();c.restore()}
|
||||
const parts=[wing(-1),wing(1),()=>c.ellipse(128,y+18,22,28,0,0,T),()=>c.arc(128,y-14,24,0,T)]
|
||||
for(const d of[-1,1])parts.push(()=>{c.moveTo(128+d*8,y-34);c.lineTo(128+d*22,y-60);c.lineTo(128+d*22,y-24);c.closePath()})
|
||||
c.lineWidth=16;c.strokeStyle='#fff';for(const f of parts)c.beginPath(),f(),c.stroke()
|
||||
c.fillStyle='#111';for(const f of parts)c.beginPath(),f(),c.fill()
|
||||
c.lineWidth=3;c.strokeStyle='#fff'
|
||||
for(const d of[-1,1]){c.save();c.translate(128+d*14,y);c.scale(d,1);c.rotate(-.45*w);for(const[x,yy]of E.slice(1,4))c.beginPath(),c.moveTo(4,0),c.lineTo(x,yy-10),c.stroke();c.restore()}
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*10,y-16,7,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*9,y-15,3.8,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*9-1.5,y-17,1.4,0,T),c.fill()
|
||||
for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*3,y-3),c.lineTo(128+d*7,y+5),c.lineTo(128+d*9,y-3),c.closePath(),c.fill()
|
||||
c.lineWidth=3;c.beginPath();c.moveTo(118,y-4);c.quadraticCurveTo(128,y,138,y-4);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// bowling ball rolls into three pins, they tumble up and spin back down into place, the ball rolls off into the distance and a new one pops in
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
const shape=c=>{c.beginPath();c.moveTo(-9,36);c.bezierCurveTo(-22,16,-16,-4,-7,-16);c.bezierCurveTo(-3,-22,-14,-28,-11,-36);c.arc(0,-36,11,PI,0);c.bezierCurveTo(14,-28,3,-22,7,-16);c.bezierCurveTo(16,-4,22,16,9,36);c.closePath()}
|
||||
const pin=(c,x,y,s,a)=>{
|
||||
c.save();c.translate(x,y);c.rotate(a);c.scale(s,s);c.translate(0,5.5);c.lineWidth=7/s
|
||||
shape(c);c.fill();c.stroke()
|
||||
c.save();shape(c);c.clip();c.fillStyle='#111';c.fillRect(-20,-22,40,4);c.fillRect(-20,-15,40,4);c.restore()
|
||||
c.restore()
|
||||
}
|
||||
const ball=(c,x,y,r)=>{
|
||||
c.beginPath();c.arc(x,y,r,0,T);c.lineWidth=16*r/34;c.strokeStyle='#fff';c.stroke();c.fillStyle='#111';c.fill();c.lineWidth=7*r/34;c.strokeStyle='#111';c.stroke()
|
||||
const a=x/30;c.fillStyle='#fff'
|
||||
for(const[hx,hy,s]of[[6,-20,5],[20,-11,5],[9,4,6]])c.beginPath(),c.arc(x+(hx*cos(a)-hy*sin(a))*r/34,y+(hx*sin(a)+hy*cos(a))*r/34,s*r/34,0,T),c.fill()
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
}
|
||||
// x, base y, scale, then how far it splays sideways, how high it hops and which way it spins
|
||||
const PINS=[[172,178,1.05,0,56,1],[146,208,1.2,-30,50,-1],[198,208,1.2,-12,42,1]]
|
||||
export default(c,t)=>{
|
||||
const roll=t<.22,bx=roll?60+32*t/.22:92+80*(t-.22)/.28,by=roll?178:178-24*(t-.22)/.28,bs=roll?1:max(0,1-(t-.22)/.28)
|
||||
c.translate(0,-8)
|
||||
if(roll)for(const o of[0,.5])D(c,()=>c.arc(bx,by,39,PI*(.75+o)+bx/30,PI*(1.05+o)+bx/30))
|
||||
if(t>=.22&&t<.36){const k=sin(PI*(t-.22)/.14);for(let j=0;j<5;j++){const b=-PI*.85+j*PI*.3;D(c,()=>{c.moveTo(124+cos(b)*22*k,166+sin(b)*22*k);c.lineTo(124+cos(b)*46*k,166+sin(b)*46*k)})}}
|
||||
if(t>=.82){const u=(t-.82)/.18;ball(c,60,178,30*(u+.35*sin(PI*u)))}
|
||||
else if(bs>.05)ball(c,bx,by,30*bs)
|
||||
for(const[x,y,s,dx,h,sp]of PINS){
|
||||
const e=(t-.24)/.52,hop=e>0&&e<1?sin(PI*e):0,w=t>=.76&&t<.92?.12*sin(T*(t-.76)/.08)*(1-(t-.76)/.16):0
|
||||
if(hop)pin(c,x+dx*hop,y-41.5*s-h*hop,s,sp*T*e)
|
||||
else{c.save();c.translate(x,y);c.rotate(w);pin(c,0,-41.5*s,s,0);c.restore()}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// sleepy candle in a little holder, its flame flickering and leaning while glow lines pulse around it
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
export default(c,t)=>{
|
||||
const L=9*sin(T*t)+4*sin(3*T*t+1),H=1+.1*sin(2*T*t+.5),g=.5+.5*sin(2*T*t)
|
||||
for(const[w,s]of[[25,'#111'],[11,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(200,206,15,-PI*.7,PI*.6),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.ellipse(128,218,80,16,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(94,122);c.lineTo(94,214);c.quadraticCurveTo(128,226,162,214);c.lineTo(162,122);c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(128,122,34,9,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(140,128);c.lineTo(140,160);c.arc(146,160,6,PI,0,true);c.lineTo(152,130);c.fill();c.lineWidth=6;c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*16,168,4,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128,174,8,.2*PI,.8*PI);c.stroke()
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(128+d*16,166,8,1.15*PI,1.85*PI),c.stroke()
|
||||
c.lineWidth=6;c.beginPath();c.moveTo(128,118);c.lineTo(128,104);c.stroke()
|
||||
const tx=128+L,ty=98-62*H
|
||||
for(const a of[-2.6,-2,-1.15,-.55])for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(128+cos(a)*(46+4*g),74+sin(a)*(46+4*g)),c.lineTo(128+cos(a)*(58+8*g),74+sin(a)*(58+8*g)),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
const fl=(s,b)=>{c.beginPath();c.moveTo(128+L*s,98-(98-ty)*s);c.quadraticCurveTo(128+18*s+L*.3,70+28*(1-s),128+16*s,98);c.arc(128,98,16*s,0,PI);c.quadraticCurveTo(128-18*s+L*.3,70+28*(1-s),128+L*s,98-(98-ty)*s)}
|
||||
fl(1);c.fill();c.stroke()
|
||||
c.fillStyle='#111';fl(.5);c.fill();c.fillStyle='#fff'
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// carrot tugged at in its soil mound, then pops up out of the ground happy with dirt flying, and sinks back down
|
||||
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 mound=c=>{c.beginPath();c.moveTo(22,238);c.bezierCurveTo(28,196,82,184,128,184);c.bezierCurveTo(174,184,228,196,234,238);c.closePath()}
|
||||
export default(c,t)=>{
|
||||
const r=t<.3?10*sin(PI*((t/.1)%1))**2:t<.42?118*ease((t-.3)/.12):t<.64?118+4*sin((t-.42)/.22*T):118*(1-ease((t-.64)/.28))
|
||||
const y=184-r,out=r>60,strain=t<.3,sw=t<.3?.25*sin(6*T*t):.08*sin(2*T*t)
|
||||
if(r>20){c.fillStyle='#111';c.beginPath();c.ellipse(128,190,30,6,0,0,T);c.fill();c.fillStyle='#fff'}
|
||||
c.save();c.beginPath();c.rect(0,0,256,232);c.clip();c.translate(128,y)
|
||||
for(const a of[-.42,0,.42]){
|
||||
c.save();c.rotate(a+sw*(a?1:-1));for(const[w,s]of[[13,'#111'],[5,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(0,-8),c.lineTo(0,-34),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.beginPath();c.ellipse(0,-46,10,17,0,0,T);c.fill();c.stroke();c.lineWidth=4;c.beginPath();c.moveTo(0,-36);c.lineTo(0,-56);c.stroke();c.restore()
|
||||
}
|
||||
c.lineWidth=7;c.beginPath();c.moveTo(-32,2);c.quadraticCurveTo(-32,-10,-18,-10);c.lineTo(18,-10);c.quadraticCurveTo(32,-10,32,2);c.lineTo(5,120);c.quadraticCurveTo(0,128,-5,120);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const[x,yy,d]of[[-27,40,1],[-22,66,1],[25,52,-1],[19,80,-1]])c.beginPath(),c.moveTo(x,yy),c.lineTo(x+d*10,yy),c.stroke()
|
||||
c.lineWidth=5
|
||||
if(strain)for(const d of[-1,1])c.beginPath(),c.moveTo(d*6,10),c.lineTo(d*16,16),c.lineTo(d*6,22),c.stroke()
|
||||
else{c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(d*12,16,4.5,6,0,0,T),c.fill();c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(d*12-1.5,14,1.8,0,T),c.fill()}
|
||||
if(out){c.beginPath();c.arc(0,30,7,.1*PI,.9*PI);c.stroke()}else{c.beginPath();c.moveTo(-6,32);c.lineTo(6,32);c.stroke()}
|
||||
c.restore()
|
||||
c.lineWidth=7;mound(c);c.fill();c.stroke()
|
||||
c.lineWidth=3;for(const[x,yy,rr]of[[64,214,4],[90,200,3],[176,206,4],[196,222,3],[112,224,3],[150,218,4]])c.beginPath(),c.arc(x,yy,rr,0,T),c.stroke()
|
||||
if(t>=.3&&t<.5){const u=(t-.3)/.2;c.lineWidth=4;for(const[vx,vy]of[[-1,1],[-.5,1.3],[.5,1.25],[1,1.05],[.1,1.4]]){const x=128+vx*70*u,yy=186-vy*120*u+150*u*u;c.beginPath();c.arc(x,yy,4.5,0,T);c.fill();c.stroke()}}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// caterpillar crawling along a twig, a hump rolling through its segments from tail to head
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t)=>{
|
||||
c.beginPath();c.moveTo(60,222);c.quadraticCurveTo(52,246,82,248);c.quadraticCurveTo(84,228,60,222);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(62,226);c.quadraticCurveTo(66,240,80,246);c.stroke();c.lineWidth=7
|
||||
c.beginPath();c.roundRect(14,206,228,20,10);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const x of[44,116,196])c.beginPath(),c.moveTo(x,216),c.lineTo(x+18,216),c.stroke()
|
||||
const s=[...Array(7)].map((_,i)=>{const p=t*T-i*.9,l=max(0,sin(p));return[34+i*25-5*cos(p),186-20*l*l]})
|
||||
for(const[x,y]of s){
|
||||
c.lineWidth=5;for(const d of[-9,9])c.beginPath(),c.ellipse(x+d,y+20,5,4,0,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.arc(x,y,20,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(x,y-7,4.5,0,T);c.fill();c.fillStyle='#fff'
|
||||
}
|
||||
const p=t*T-7*.9,l=max(0,sin(p)),hx=34+7*25-5*cos(p)+2,hy=172-16*l*l
|
||||
for(const d of[-1,1]){
|
||||
const ex=hx+d*12+3*sin(t*T*2+d),ey=hy-46
|
||||
for(const[w,st]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(hx+d*8,hy-20),c.quadraticCurveTo(hx+d*6,hy-36,ex,ey),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.arc(ex,ey,6,0,T);c.fill();c.stroke()
|
||||
}
|
||||
c.lineWidth=7;c.beginPath();c.arc(hx,hy,27,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const x of[hx-4,hx+14])c.beginPath(),c.ellipse(x,hy-4,5,7,0,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[hx-6,hx+12])c.beginPath(),c.arc(x,hy-7,2,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(hx+5,hy+8,7,.15*PI,.85*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
// two cherries on joined stems swinging like a pendulum, each lagging a little, the leaf flapping along
|
||||
// the black cherries get a white rim so they show on dark backgrounds
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
export default(c,t)=>{
|
||||
const P=[128,30],ch=[[-.3,152,0],[.27,140,.35]]
|
||||
const ends=ch.map(([b,L,ph])=>{const a=b+.3*sin(T*t-ph);return[P[0]+L*sin(a),P[1]+L*cos(a),a]})
|
||||
for(const[w,s]of[[13,'#111'],[5,'#fff']]){c.lineWidth=w;c.strokeStyle=s;for(const[x,y,a]of ends)c.beginPath(),c.moveTo(...P),c.quadraticCurveTo((P[0]+x)/2-20*cos(a)*Math.sign(a),(P[1]+y)/2,x,y-30),c.stroke()}
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.save();c.translate(...P);c.rotate(-.5+.18*sin(T*t-.6));c.beginPath();c.moveTo(0,0);c.bezierCurveTo(-14,-26,-46,-30,-62,-14);c.bezierCurveTo(-46,4,-14,10,0,0);c.fill();c.stroke();c.lineWidth=4;c.beginPath();c.moveTo(-4,-2);c.quadraticCurveTo(-32,-12,-56,-14);c.stroke();c.restore()
|
||||
c.lineWidth=7;c.beginPath();c.arc(...P,8,0,T);c.fill();c.stroke()
|
||||
for(const[k,[x,y]]of ends.entries()){
|
||||
c.beginPath();c.arc(x,y,36,0,T);c.lineWidth=16;c.strokeStyle='#fff';c.stroke();c.fillStyle='#111';c.fill();c.lineWidth=7;c.strokeStyle='#111';c.stroke()
|
||||
c.strokeStyle='#fff';c.fillStyle='#fff';c.lineWidth=5
|
||||
c.beginPath();c.arc(x,y,24,PI*1.12,PI*1.4);c.stroke()
|
||||
if(k)for(const d of[-1,1])c.beginPath(),c.ellipse(x+d*11,y+2,4,5.5,0,0,T),c.fill()
|
||||
else{c.beginPath();c.ellipse(x-11,y+2,4,5.5,0,0,T);c.fill();c.lineWidth=4;c.beginPath();c.moveTo(x+6,y+4);c.quadraticCurveTo(x+11,y-2,x+16,y+4);c.stroke()}
|
||||
c.lineWidth=4;c.beginPath();c.arc(x,y+11,6,.15*PI,.85*PI);c.stroke()
|
||||
c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// cow chewing its cud side to side, the bell under its chin swinging and one ear flicking
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const delay=80
|
||||
export default(c,t)=>{
|
||||
const j=5*sin(2*T*t),bs=.3*sin(2*T*t-.8),ef=t>.55&&t<.8?sin(PI*(t-.55)/.25):0
|
||||
c.beginPath();c.rect(100,150,56,52);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(92,192,72,13,6);c.fill();c.stroke()
|
||||
c.save();c.translate(128,204);c.rotate(bs)
|
||||
c.beginPath();c.moveTo(-9,0);c.lineTo(9,0);c.lineTo(16,28);c.quadraticCurveTo(0,34,-16,28);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(0,35,5,0,T);c.fill();c.restore();c.fillStyle='#fff'
|
||||
for(const d of[-1,1]){
|
||||
c.beginPath();c.moveTo(128+d*22,58);c.quadraticCurveTo(128+d*46,54,128+d*46,28);c.quadraticCurveTo(128+d*34,42,128+d*14,50);c.closePath();c.fill();c.stroke()
|
||||
c.save();c.translate(128+d*46,90);c.rotate(d*(.3+(d>0?.45*ef:0)))
|
||||
c.beginPath();c.ellipse(d*26,0,28,12,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(d*28,0,15,4,0,0,T);c.stroke();c.lineWidth=7;c.restore()
|
||||
}
|
||||
const head=()=>{c.beginPath();c.roundRect(78,44,100,128,[46,46,40,40])}
|
||||
head();c.fill();c.save();c.clip();c.fillStyle='#111'
|
||||
c.beginPath();c.ellipse(90,60,28,22,.5,0,T);c.fill();c.beginPath();c.ellipse(180,128,18,28,-.3,0,T);c.fill();c.restore()
|
||||
head();c.stroke();c.fillStyle='#fff'
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(116,50);c.quadraticCurveTo(120,36,128,46);c.quadraticCurveTo(134,34,140,50);c.stroke();c.lineWidth=7
|
||||
c.fillStyle='#111';for(const x of[108,148])c.beginPath(),c.arc(x,100,7,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[106,146])c.beginPath(),c.arc(x,97,2.5,0,T),c.fill()
|
||||
c.beginPath();c.ellipse(128+j,148,50,30,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(128+j+d*18,144,5,8,-d*.25,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(114+j,164+j*.5);c.quadraticCurveTo(128+j*1.6,169,142+j,164-j*.5);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// Newton's cradle: the end balls take turns swinging out and clacking back while the middle three stay still
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
export default(c,t)=>{
|
||||
const A=.42,L=104,P=44,sw=-A*sin(t*T)
|
||||
for(const d of[-1,1])D(c,()=>{c.moveTo(128+d*96,40);c.lineTo(128+d*110,222)},14,5)
|
||||
c.beginPath();c.roundRect(10,218,236,20,9);c.fill();c.stroke()
|
||||
const k=t<.1?176:t>=.5&&t<.6?80:0
|
||||
if(k)for(const a of[-.6,0,.6])D(c,()=>{c.moveTo(k+sin(a)*22,P+L-cos(a)*22);c.lineTo(k+sin(a)*38,P+L-cos(a)*38)})
|
||||
for(let i=0;i<5;i++){
|
||||
const x0=64+32*i,a=i==0&&t<.5||i==4&&t>=.5?sw:0,x=x0+L*sin(a),y=P+L*cos(a)
|
||||
D(c,()=>{c.moveTo(x0,P);c.lineTo(x,y)},9,3)
|
||||
c.beginPath();c.arc(x,y,16,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=3;c.beginPath();c.arc(x,y,9,PI*1.1,PI*1.5);c.stroke();c.lineWidth=7
|
||||
}
|
||||
c.beginPath();c.roundRect(22,28,212,16,8);c.fill();c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// mouse pointer glides onto a like button and clicks it: the button presses in, a ring ripples out and the heart fills
|
||||
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 go=ease(t/.3)-ease((t-.62)/.3),px=174-24*go,py=132-28*go,click=t>=.34&&t<.42,on=t>=.36&&t<.9,rp=(t-.36)/.3
|
||||
const by=click?5:0
|
||||
c.lineWidth=10
|
||||
c.beginPath();c.roundRect(22,40+by,212,96,48);c.fill();c.stroke()
|
||||
c.save();c.translate(124,90+by);c.scale(2.4,2.4)
|
||||
c.beginPath();c.moveTo(0,10);c.bezierCurveTo(-18,-2,-12,-18,0,-8);c.bezierCurveTo(12,-18,18,-2,0,10);c.closePath()
|
||||
c.restore();if(on)c.fillStyle='#111',c.fill(),c.fillStyle='#fff';c.lineWidth=8;c.stroke()
|
||||
if(rp>0&&rp<1){const r=14+40*rp;for(const[w,s]of[[15,'#111'],[6,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(150,104,r,0,T),c.stroke()
|
||||
for(const a of[-1.9,-1.1,-.3])for(const[w,s]of[[15,'#111'],[6,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(150+cos(a)*(r+12),104+sin(a)*(r+12)),c.lineTo(150+cos(a)*(r+26),104+sin(a)*(r+26)),c.stroke()}
|
||||
c.lineWidth=10;c.strokeStyle='#111'
|
||||
c.save();c.translate(px,py);c.scale(click?.9:1,click?.9:1)
|
||||
c.beginPath();for(const[x,y]of[[0,0],[0,96],[24,74],[42,112],[61,102],[43,66],[74,64]])c.lineTo(x,y);c.closePath();c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// snare drum with two sticks taking turns hitting it, the head dipping and impact lines on every hit
|
||||
const{sin,cos,PI,abs,max}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
export default(c,t)=>{
|
||||
const top=128,bot=192,rx=86,ry=26,h=[abs(sin(PI*t)),abs(cos(PI*t))]
|
||||
const dip=4*max(0,1-Math.min(...h)/.25)
|
||||
c.beginPath();c.moveTo(128-rx,top);c.lineTo(128-rx,bot);c.ellipse(128,bot,rx,ry,0,PI,0,true);c.lineTo(128+rx,top);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5;for(const y of[top+12,bot-12])c.beginPath(),c.ellipse(128,y,rx,ry,0,.08,PI-.08),c.stroke()
|
||||
c.lineWidth=4;c.beginPath()
|
||||
for(let k=0;k<=8;k++){const x=52+k*19,e=Math.sqrt(1-((x-128)/rx)**2)*ry;c.lineTo(x,k%2?bot-12+e:top+12+e)}
|
||||
c.stroke();c.lineWidth=7
|
||||
c.beginPath();c.ellipse(128,top,rx,ry-dip,0,0,T);c.fill();c.stroke()
|
||||
for(const d of[-1,1]){
|
||||
const k=h[d<0?0:1],px=128+d*116,py=92,a=(d<0?.335:PI-.335)-d*.75*k,tx=px+cos(a)*97,ty=py+sin(a)*97
|
||||
if(k<.2)for(const b of[-.7,0,.7])D(c,()=>{c.moveTo(tx+sin(b)*16,top-6-cos(b)*16);c.lineTo(tx+sin(b)*32,top-6-cos(b)*32)})
|
||||
D(c,()=>{c.moveTo(px,py);c.lineTo(tx,ty)},17,8)
|
||||
c.beginPath();c.ellipse(tx,ty,9,7,a,0,T);c.fill();c.stroke()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// elephant lifting its trunk and spraying a shower of water back over its head onto its back
|
||||
const{sin,cos,PI,atan2}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const sm=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
export default(c,t)=>{
|
||||
const k=t<.3?sm(t/.3):t<.65?1:sm(1-(t-.65)/.25),L=(a,b)=>a+(b-a)*k,fl=.07*sin(2*T*t)
|
||||
const B=[198,148],C=[L(224,248),L(180,116)],P=[L(212,232),L(224,50)]
|
||||
const q=s=>[0,1].map(i=>(1-s)**2*B[i]+2*s*(1-s)*C[i]+s*s*P[i]),qd=s=>[0,1].map(i=>2*(1-s)*(C[i]-B[i])+2*s*(P[i]-C[i]))
|
||||
for(const x of[54,86,120,150]){
|
||||
c.beginPath();c.roundRect(x,172,28,52,[0,0,10,10]);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const o of[8,20])c.beginPath(),c.arc(x+o,224,4,PI,0),c.stroke();c.lineWidth=7
|
||||
}
|
||||
for(const[l,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(42,146),c.quadraticCurveTo(26,160,28,186),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5;c.beginPath();c.moveTo(28,184);c.quadraticCurveTo(20,196,28,202);c.quadraticCurveTo(36,196,28,184);c.fill();c.stroke();c.lineWidth=7
|
||||
c.beginPath();c.ellipse(108,150,72,54,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(176,114,46,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(...B);c.quadraticCurveTo(...C,...P)
|
||||
for(const[l,s]of[[34,'#111'],[22,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=3
|
||||
for(const s of[.55,.7,.85]){const[x,y]=q(s),[dx,dy]=qd(s),a=atan2(dy,dx)+PI/2;c.beginPath();c.moveTo(x-7*cos(a),y-7*sin(a));c.lineTo(x+7*cos(a),y+7*sin(a));c.stroke()}
|
||||
const[dx,dy]=qd(1);c.lineWidth=5;c.beginPath();c.ellipse(...P,15,7,atan2(dy,dx)+PI/2,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(176,114,42,0,T);c.fill()
|
||||
c.lineWidth=7;c.save();c.translate(150,118);c.scale(1+fl,1)
|
||||
c.beginPath();c.ellipse(0,0,30,42,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(-3,4,18,28,0,0,T);c.stroke();c.restore();c.lineWidth=7
|
||||
c.fillStyle='#111';c.beginPath();c.arc(192,100,6,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(190,98,2,0,T);c.fill()
|
||||
c.lineWidth=3;for(const o of[-5,0,5])c.beginPath(),c.moveTo(196+o-2,124),c.lineTo(196+o+2,118),c.stroke()
|
||||
c.lineWidth=4
|
||||
for(let i=0;i<8;i++){
|
||||
const s=(t-.3-i*.034)/.22;if(s<=0||s>=1)continue
|
||||
const vx=-(110+14*(i%3)),x=232+vx*s,y=50-76*s+150*s*s,a=atan2(-76+300*s,vx),r=8.5*(1-.35*s)
|
||||
c.save();c.translate(x,y);c.rotate(a);c.beginPath();c.arc(0,0,r,-PI/2,PI/2);c.lineTo(-r*2.4,0);c.closePath();c.restore();c.fill();c.stroke()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// desk fan with its blades whirring and its head turning slowly side to side
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
export default(c,t)=>{
|
||||
const y=.55*sin(t*T),k=cos(y),sx=22*sin(y)
|
||||
for(const[w,s]of[[30,'#111'],[16,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(128+sx*.4,170),c.lineTo(128,214),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.ellipse(128,220,62,16,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(160,220,8,4,0,0,T);c.fill();c.fillStyle='#fff'
|
||||
c.save();c.translate(128+sx,98);c.scale(k,1)
|
||||
c.beginPath();c.arc(0,0,82,0,T);c.fill();c.stroke()
|
||||
const r=t*T*7/3
|
||||
for(let b=0;b<3;b++){
|
||||
const a=r+b*T/3
|
||||
c.beginPath();c.moveTo(cos(a)*14,sin(a)*14)
|
||||
c.bezierCurveTo(cos(a-.5)*48,sin(a-.5)*48,cos(a-.32)*72,sin(a-.32)*72,cos(a+.05)*70,sin(a+.05)*70)
|
||||
c.bezierCurveTo(cos(a+.5)*64,sin(a+.5)*64,cos(a+.55)*36,sin(a+.55)*36,cos(a+.6)*14,sin(a+.6)*14)
|
||||
c.closePath();c.lineWidth=6;c.fill();c.stroke()
|
||||
}
|
||||
c.lineWidth=3;for(let s=0;s<12;s++){const a=s*T/12;c.beginPath();c.moveTo(cos(a)*24,sin(a)*24);c.lineTo(cos(a)*78,sin(a)*78);c.stroke()}
|
||||
c.beginPath();c.arc(0,0,52,0,T);c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.arc(0,0,82,0,T);c.stroke()
|
||||
c.beginPath();c.arc(0,0,20,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(0,0,6,0,T);c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// faucet with a drop swelling at the spout, letting go, and splashing into a puddle with a ripple
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
export default(c,t)=>{
|
||||
const X=170,ty=150,py=222
|
||||
c.lineWidth=7
|
||||
c.beginPath();c.ellipse(X,py,62,14,0,0,T);c.fill();c.stroke()
|
||||
if(t>=.62){const p=(t-.62)/.38;c.lineWidth=5;c.beginPath();c.ellipse(X,py,10+44*p,2+9*p,0,0,T);c.stroke()
|
||||
if(p<.7)for(const d of[-1,1]){const q=p/.7;c.lineWidth=6;c.beginPath();c.arc(X+d*(10+26*q),py-8-44*4*q*(1-q),7*(1-q*.4),0,T);c.fill();c.stroke()}}
|
||||
for(const[w,s]of[[52,'#111'],[38,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(44,96),c.lineTo(126,96),c.quadraticCurveTo(X,96,X,132),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.roundRect(X-26,126,52,20,7);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(20,56,28,80,9);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(92,70);c.lineTo(92,46);c.stroke()
|
||||
for(const[w,s]of[[24,'#111'],[10,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(60,40),c.lineTo(124,40),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.beginPath();c.arc(92,40,11,0,T);c.fill();c.stroke()
|
||||
const drop=(y,r,s)=>{c.beginPath();c.moveTo(X,y-r*s);c.quadraticCurveTo(X+r*.9,y-r*.4,X+r,y);c.arc(X,y,r,0,PI);c.quadraticCurveTo(X-r*.9,y-r*.4,X,y-r*s);c.lineWidth=6;c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(X-r*.38,y-r*.05,r*.2,0,T);c.fill();c.fillStyle='#fff'}
|
||||
if(t<.46){const g=t/.46,r=6+10*g;drop(ty+r*.5+6*g,r,1.5+.9*g)}
|
||||
else if(t<.62){const f=(t-.46)/.16;drop(ty+20+(py-12-ty-20)*f*f,15,2.2)}
|
||||
else drop(ty+3,6,1.4)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// two meshing gears turning against each other, the small one spinning faster
|
||||
// the small gear's angle comes from rolling contact, offset half a tooth so its gap meets the big gear's tooth
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const gear=(c,x,y,n,R,th,holes)=>{
|
||||
const p=T/n,ri=R-10,ro=R+8
|
||||
c.beginPath()
|
||||
for(let k=0;k<n;k++){const a=th+k*p;for(const[f,r]of[[-.5,ri],[-.3,ri],[-.18,ro],[.18,ro],[.3,ri]])c.lineTo(x+cos(a+f*p)*r,y+sin(a+f*p)*r)}
|
||||
c.closePath();c.lineWidth=7;c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(x,y,R-22,0,T);c.stroke()
|
||||
for(let k=0;k<holes;k++){const a=th+k*T/holes;c.beginPath();c.arc(x+cos(a)*(R-38)*.95,y+sin(a)*(R-38)*.95,R*.13,0,T);c.stroke()}
|
||||
c.lineWidth=7;c.beginPath();c.arc(x,y,R*.2,0,T);c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(x,y,6,0,T);c.fill();c.fillStyle='#fff'
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const N=12,n=8,m=11,R=N*m/2,r=n*m/2,f=-.6,bx=90,by=158,sx=bx+(R+r)*cos(f),sy=by+(R+r)*sin(f)
|
||||
const tb=t*T/6,ts=f+PI+PI/n-(N/n)*(tb-f)
|
||||
gear(c,bx,by,N,R,tb,6)
|
||||
gear(c,sx,sy,n,r,ts,0)
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// hedgehog curls into a spiky ball, rolls with speed lines, then uncurls and sniffs
|
||||
// the spiky coat is a zigzag band whose sweep grows from its back to all the way round
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const sm=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
export default(c,t)=>{
|
||||
const k=t<.15?0:t<.3?sm((t-.15)/.15):t<.7?1:t<.85?sm(1-(t-.7)/.15):0,u=1-k
|
||||
const ro=t>=.3&&t<.7?2*T*(t-.3)/.4:0,rx=70-18*k,ry=48+4*k,cx=128,cy=158+4*k-(k==1?3*Math.abs(sin(2*ro)):0),sn=k?0:1.5*sin(8*T*t)
|
||||
const P=(a,s)=>[cx+(rx+s)*cos(a),cy+(ry+s)*sin(a)]
|
||||
if(k==1){c.lineWidth=7;for(const[o,y]of[[0,-20],[14,4],[4,26]]){const p=(t*5+o/14)%1,x0=cx-rx-24-o-8*p
|
||||
for(const[l,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(x0,cy+y),c.lineTo(x0-30,cy+y),c.stroke()}
|
||||
c.strokeStyle='#111';c.lineWidth=7}
|
||||
if(u>.02)for(const x of[-34,30])c.beginPath(),c.ellipse(cx+x,cy+ry+4,15*u,8*u,0,0,T),c.fill(),c.stroke()
|
||||
c.beginPath();c.ellipse(cx,cy,rx,ry,0,0,T);c.fill();c.stroke()
|
||||
if(u>.02){
|
||||
c.beginPath();c.ellipse(cx+rx*.8+8*u,cy+8+sn*.3,28*u,18*u,-.2,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(cx+rx*.8+34*u,cy+2+sn,7*u,0,T);c.fill()
|
||||
c.beginPath();c.arc(cx+rx*.55,cy-ry*.1,5.5*u,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(cx+rx*.55-1.5,cy-ry*.1-2,2*u,0,T);c.fill()
|
||||
}
|
||||
const S=PI*(1.05+.95*k),a0=-.42*PI+ro,n=Math.round(S/(T/24)),I=a=>[cx+.9*rx*cos(a),cy+.9*ry*sin(a)],E=I(a0),band=()=>{
|
||||
c.beginPath();for(let i=0;i<=2*n;i++){const a=a0-i*S/(2*n);c.lineTo(...P(a,i%2?18:2))}
|
||||
c.lineTo(...I(a0-S));c.quadraticCurveTo(cx+.45*rx+k*(E[0]-cx-.45*rx),cy+.05*ry+k*(E[1]-cy-.05*ry),...E);c.closePath()}
|
||||
band();c.fill();c.stroke()
|
||||
c.lineWidth=4;for(let i=3;i<n-2;i+=2){const a=a0-i*S/n;c.beginPath();c.moveTo(cx+rx*.74*cos(a),cy+ry*.74*sin(a));c.lineTo(...P(a,-8));c.stroke()}
|
||||
c.lineWidth=7
|
||||
if(u>.02){c.beginPath();c.arc(cx+rx*.3,cy-ry*.66,8*u,0,T);c.fill();c.stroke()}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// hot dog getting a zigzag of mustard squirted along it as the bottle slides across, then the line wipes off for the loop
|
||||
// the black sausage gets a white rim so it shows on dark backgrounds
|
||||
const{sin,PI,min,max,abs}=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 zy=x=>149+8*sin((x-50)/156*T*5)
|
||||
export default(c,t)=>{
|
||||
const sq=t<.6,head=50+156*ease(t/.6),tail=50+156*ease((t-.78)/.22),bx=t<.78?head:206-156*ease((t-.78)/.22),by=118-(t>=.78?34*sin(PI*min(1,(t-.78)/.22)):0)
|
||||
c.beginPath();c.moveTo(34,160);c.quadraticCurveTo(34,124,80,122);c.lineTo(176,122);c.quadraticCurveTo(222,124,222,160);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(16,130,224,38,19);c.lineWidth=16;c.strokeStyle='#fff';c.stroke();c.fillStyle='#111';c.fill();c.lineWidth=7;c.strokeStyle='#111';c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=5;for(const[x0,x1]of[[30,44],[212,226]])c.beginPath(),c.moveTo(x0,140),c.lineTo(x1,138),c.stroke()
|
||||
if(head-tail>1)for(const[w,s]of[[12,'#111'],[6,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();for(let x=tail;x<=head;x+=2)c.lineTo(x,zy(x));c.stroke()}
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
c.beginPath();c.moveTo(30,160);c.quadraticCurveTo(128,172,226,160);c.quadraticCurveTo(226,206,180,206);c.lineTo(76,206);c.quadraticCurveTo(30,206,30,160);c.fill();c.stroke()
|
||||
const happy=t>=.6&&t<.78
|
||||
c.fillStyle='#111'
|
||||
if(happy){c.lineWidth=5;for(const x of[106,150])c.beginPath(),c.arc(x,186,7,PI*1.15,PI*1.85),c.stroke()}
|
||||
else{for(const x of[106,150])c.beginPath(),c.ellipse(x,184,5,6.5,0,0,T),c.fill();c.fillStyle='#fff';for(const x of[104,148])c.beginPath(),c.arc(x,182,2,0,T),c.fill()}
|
||||
c.lineWidth=4.5;c.beginPath();c.arc(128,190,8,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=3;for(const x of[86,170])for(const o of[-5,0,5])c.beginPath(),c.moveTo(x+o-2,198),c.lineTo(x+o+2,191),c.stroke()
|
||||
c.lineWidth=7;c.fillStyle='#fff'
|
||||
if(sq&&t>.02)for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(bx,by),c.lineTo(bx,zy(bx)-2),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
const k=sq?1-.1*abs(sin(10*T*t)):1
|
||||
c.save();c.translate(bx,by);c.rotate(t>=.78?-.4*sin(PI*min(1,(t-.78)/.22)):0)
|
||||
c.beginPath();c.moveTo(-5,0);c.lineTo(-12,-24);c.lineTo(12,-24);c.lineTo(5,0);c.closePath();c.fill();c.stroke()
|
||||
c.scale(k,1);c.beginPath();c.roundRect(-22,-92,44,70,12);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const y of[-66,-48])c.beginPath(),c.moveTo(-12,y),c.lineTo(12,y),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// icicles hanging from a snowy ledge, a drop swelling on the longest one, falling and splashing into a puddle
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
export default(c,t)=>{
|
||||
c.beginPath();c.ellipse(128,226,82,17,0,0,T);c.fill();c.stroke()
|
||||
const s=(t-.68)/.32
|
||||
if(t>=.68){
|
||||
c.lineWidth=4;for(const k of[0,.4]){const q=s-k;if(q>0&&q<.9)c.beginPath(),c.ellipse(128,226,14+62*q,4+11*q,0,0,T),c.stroke()}
|
||||
c.lineWidth=4;for(const v of[-1,-.4,.4,1])if(s<.8)c.beginPath(),c.arc(128+v*50*s,220-80*s+100*s*s,7-5*s,0,T),c.fill(),c.stroke()
|
||||
}
|
||||
c.lineWidth=7
|
||||
for(const[x,w,l]of[[54,24,50],[90,28,78],[128,32,104],[164,28,72],[200,22,46]]){
|
||||
c.beginPath();c.moveTo(x-w/2,50);c.quadraticCurveTo(x-w*.18,50+l*.6,x,50+l);c.quadraticCurveTo(x+w*.18,50+l*.6,x+w/2,50);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(x-w*.18,58);c.quadraticCurveTo(x-w*.12,50+l*.45,x-2,50+l*.7);c.stroke();c.lineWidth=7
|
||||
}
|
||||
c.beginPath();c.roundRect(16,34,224,16,4);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();for(const x of[70,136,196])c.moveTo(x,38),c.lineTo(x,46);c.stroke();c.lineWidth=7
|
||||
c.beginPath();c.moveTo(12,40);c.quadraticCurveTo(14,18,40,18);c.quadraticCurveTo(70,6,100,16);c.quadraticCurveTo(136,4,170,16);c.quadraticCurveTo(204,6,226,18);c.quadraticCurveTo(246,22,244,40)
|
||||
c.quadraticCurveTo(236,48,222,40);c.quadraticCurveTo(176,34,150,38);c.quadraticCurveTo(144,52,134,40);c.quadraticCurveTo(80,34,44,38);c.quadraticCurveTo(36,50,28,40);c.quadraticCurveTo(18,46,12,40);c.fill();c.stroke()
|
||||
const drop=(x,y,r)=>{c.lineWidth=5;c.beginPath();c.moveTo(x,y-r*2.2);c.bezierCurveTo(x+r*.4,y-r*1.2,x+r,y-r*.6,x+r,y);c.arc(x,y,r,0,PI);c.bezierCurveTo(x-r,y-r*.6,x-r*.4,y-r*1.2,x,y-r*2.2);c.fill();c.stroke()}
|
||||
if(t<.5){const r=3+8*t/.5;drop(128,148+r*1.8,r)}
|
||||
else if(t<.68){const f=(t-.5)/.18;drop(128,170+f*f*50,10)}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// koala hugging a branch and dozing off, its head slowly nodding while Z's drift up
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=20,delay=90
|
||||
export default(c,t)=>{
|
||||
const a=.07*sin(t*T),dy=3+3*sin(t*T)
|
||||
c.beginPath();c.ellipse(122,184,50,54,0,0,T);c.fill();c.stroke()
|
||||
c.save();c.translate(112,152);c.rotate(a);c.translate(-112,-152+dy)
|
||||
for(const[x,y,r]of[[68,84,26],[150,76,24]]){
|
||||
c.lineWidth=7;c.beginPath();c.arc(x,y,r,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const k of[-1,0,1])c.beginPath(),c.moveTo(x+k*7,y+8),c.lineTo(x+k*9,y-6),c.stroke()
|
||||
}
|
||||
c.lineWidth=7;c.beginPath();c.arc(108,112,44,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5;for(const x of[88,128])c.beginPath(),c.arc(x,104,8,.15*PI,.85*PI),c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(108,122,13,16,0,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(103,115,3,5,-.3,0,T);c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(108,140,6,.2*PI,.8*PI);c.stroke()
|
||||
c.restore()
|
||||
c.lineWidth=7;c.beginPath();c.roundRect(148,8,38,242,18);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const[x,y]of[[160,30],[174,84],[160,118],[172,236]])c.beginPath(),c.moveTo(x,y),c.quadraticCurveTo(x+4,y+10,x,y+20),c.stroke()
|
||||
for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(184,52),c.lineTo(226,30),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
for(const[x,y,r]of[[214,22,-.9],[232,46,.6]]){
|
||||
c.lineWidth=6;c.beginPath();c.ellipse(x,y,16,8,r,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=3;c.beginPath();c.moveTo(x-12*cos(r),y-12*sin(r));c.lineTo(x+12*cos(r),y+12*sin(r));c.stroke()
|
||||
}
|
||||
for(const[x0,y0,x1,y1]of[[126,172,166,154],[138,214,170,214]]){
|
||||
for(const[w,s]of[[34,'#111'],[20,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x0,y0),c.lineTo(x1,y1),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=6;c.beginPath();c.ellipse(x1+4,y1,14,12,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=3;for(const k of[-1,0,1])c.beginPath(),c.moveTo(x1+14,y1+k*5),c.lineTo(x1+20,y1+k*6),c.stroke()
|
||||
}
|
||||
for(const k of[0,.5]){
|
||||
const p=(t+k)%1,s=9*sin(PI*p),x=110-12*p,y=46-26*p
|
||||
if(s>2)for(const[w,st]of[[10,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(x-s,y-s),c.lineTo(x+s,y-s),c.lineTo(x-s,y+s),c.lineTo(x+s,y+s),c.stroke()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// lemon squeezed from both sides: it squashes, scrunches its face and squirts juice drops up and away
|
||||
const{sin,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
export default(c,t)=>{
|
||||
const s=sin(PI*min(1,max(0,(t-.12)/.46)))**1.5,sq=s>.35
|
||||
c.save();c.translate(128,150);c.scale(1-.2*s,1+.16*s)
|
||||
c.save();c.translate(10,-58);c.rotate(-.5);c.beginPath();c.ellipse(16,-6,20,9,-.2,0,T);c.fill();c.stroke();c.lineWidth=4;c.beginPath();c.moveTo(-2,-2);c.lineTo(30,-9);c.stroke();c.restore()
|
||||
c.lineWidth=14
|
||||
const nub=d=>{c.beginPath();c.ellipse(d*80,0,14,11,0,0,T)},body=()=>{c.beginPath();c.ellipse(0,0,78,58,0,0,T)}
|
||||
for(const d of[-1,1])nub(d),c.stroke();body();c.stroke()
|
||||
for(const d of[-1,1])nub(d),c.fill();body();c.fill()
|
||||
c.lineWidth=3;for(const[x,y]of[[-50,-28],[46,-34],[-56,22],[54,24],[-30,40],[34,44],[-8,-46],[20,-44]])c.beginPath(),c.arc(x,y,2.5,0,T),c.stroke()
|
||||
c.lineWidth=5;c.fillStyle='#111'
|
||||
if(sq)for(const d of[-1,1])c.beginPath(),c.moveTo(d*16,-18),c.lineTo(d*30,-10),c.lineTo(d*16,-2),c.stroke()
|
||||
else{for(const d of[-1,1])c.beginPath(),c.ellipse(d*24,-10,6,8,0,0,T),c.fill();c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(d*24-2,-13,2.5,0,T),c.fill()}
|
||||
if(sq){c.beginPath();c.ellipse(0,16,7,9,0,0,T);c.fillStyle='#111';c.fill()}
|
||||
else{c.beginPath();c.arc(0,6,11,.15*PI,.85*PI);c.stroke()}
|
||||
c.lineWidth=3;for(const d of[-1,1])for(const o of[-6,0,6])c.beginPath(),c.moveTo(d*46+o-2,14),c.lineTo(d*46+o+3,6),c.stroke()
|
||||
c.restore()
|
||||
if(s>.25)for(const d of[-1,1])for(const[w,st]of[[11,'#111'],[4,'#fff']]){c.lineWidth=w;c.strokeStyle=st;for(const y of[-22,0,22]){const x=128+d*(124-16*s);c.beginPath();c.moveTo(x,150+y);c.lineTo(x-d*12,150+y*.9);c.stroke()}}
|
||||
c.lineWidth=4;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
for(const[vx,v,t0]of[[-1,1,.3],[.35,1.15,.34],[1,.95,.38],[-.4,1.05,.43]]){
|
||||
const u=(t-t0)/.4;if(u<0||u>=1)continue
|
||||
const x=128+vx*86*u,y=88-v*362*u+546*u*u
|
||||
c.beginPath();c.moveTo(x,y-11);c.quadraticCurveTo(x+8,y-1,x+7,y+3);c.arc(x,y+3,7,0,PI);c.quadraticCurveTo(x-8,y-1,x,y-11);c.fill();c.stroke()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// lion roaring: the mane puffs out, the mouth opens wide on its fangs and roar lines burst out
|
||||
// the mane is one outline: every tuft is stroked wide first, then all of them are filled
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
const sm=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
export default(c,t)=>{
|
||||
const r=t<.3?0:t<.42?sm((t-.3)/.12):t<.8?1:sm(1-(t-.8)/.12),sh=r*1.5*sin(10*T*t),R=62+10*r,n=14
|
||||
if(r>.5)for(const d of[-1,1])for(const k of[0,1]){
|
||||
const p=((t-.42)*3+k*.5)%1,rr=104+16*p
|
||||
for(const[l,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.arc(128,140,rr,d>0?-.32:PI-.32,d>0?.32:PI+.32),c.stroke()
|
||||
}
|
||||
c.translate(sh,0)
|
||||
const L=[...Array(n)].map((_,i)=>[128+R*cos(i*T/n+.11),126+R*.94*sin(i*T/n+.11)]),tr=24+4*r
|
||||
c.lineWidth=14;c.strokeStyle='#111';for(const[x,y]of L)c.beginPath(),c.arc(x,y,tr,0,T),c.stroke()
|
||||
c.fillStyle='#fff';for(const[x,y]of L)c.beginPath(),c.arc(x,y,tr,0,T),c.fill()
|
||||
c.beginPath();c.arc(128,126,R,0,T);c.fill()
|
||||
c.lineWidth=7
|
||||
for(const d of[-1,1]){c.beginPath();c.arc(128+d*38,86,14,0,T);c.fill();c.stroke();c.lineWidth=4;c.beginPath();c.arc(128+d*38,88,6,0,T);c.stroke();c.lineWidth=7}
|
||||
c.beginPath();c.arc(128,128,50,0,T);c.fill();c.stroke()
|
||||
if(r>.5){c.lineWidth=6;for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*30,108),c.lineTo(128+d*14,116),c.lineTo(128+d*30,124),c.stroke()}
|
||||
else{
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*20,116,6.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*20-2,113,2.3,0,T),c.fill()
|
||||
}
|
||||
if(r>.05){
|
||||
const h=6+24*r,y=154+4*r
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(128,y+h/2,14+8*r,h/2+4,0,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.lineWidth=3
|
||||
for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*15*(.6+.4*r),y),c.lineTo(128+d*9*(.6+.4*r),y+6+6*r),c.lineTo(128+d*5,y+2),c.closePath(),c.fill()
|
||||
if(r>.4)for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*14,y+h+4),c.lineTo(128+d*9,y+h-6),c.lineTo(128+d*5,y+h+3),c.closePath(),c.fill()
|
||||
}
|
||||
c.fillStyle='#fff';c.lineWidth=5
|
||||
for(const d of[-1,1]){c.beginPath();c.ellipse(128+d*14,146,17,13,0,0,T);c.fill();c.stroke()}
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(128,148,10,9,0,0,T);c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])for(const[x,y]of[[10,144],[18,150],[12,152]])c.beginPath(),c.arc(128+d*x,y,1.8,0,T),c.fill()
|
||||
c.beginPath();c.moveTo(116,132);c.lineTo(140,132);c.quadraticCurveTo(140,140,128,146);c.quadraticCurveTo(116,140,116,132);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// swirl lollipop spinning its spiral round, a ribbon on the stick and a sparkle twinkling beside it
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const star=(c,x,y,r)=>{const k=r*.18;c.beginPath();c.moveTo(x,y-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(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
c.beginPath();c.roundRect(119,150,18,96,7);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(128,98,72,0,T);c.fill()
|
||||
c.save();c.clip();c.lineWidth=13;c.beginPath()
|
||||
for(let th=0;th<=T*4.6;th+=.08){const r=th/T*16,a=th-T*t;c.lineTo(128+r*cos(a),98+r*sin(a))}
|
||||
c.stroke();c.restore()
|
||||
c.lineWidth=7;c.beginPath();c.arc(128,98,72,0,T);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=6;c.beginPath();c.arc(128,98,58,PI*1.12,PI*1.38);c.stroke();c.strokeStyle='#111';c.lineWidth=7
|
||||
for(const d of[-1,1])c.beginPath(),c.moveTo(128,184),c.quadraticCurveTo(128+d*30,160,128+d*34,180),c.quadraticCurveTo(128+d*30,200,128,184),c.fill(),c.stroke()
|
||||
for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*3,188),c.lineTo(128+d*14,214),c.lineTo(128+d*22,206),c.closePath(),c.fill(),c.stroke()
|
||||
c.beginPath();c.arc(128,185,7,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const[x,y,ph,R]of[[214,36,0,15],[44,170,.5,10]]){const r=R*max(0,sin(PI*((t*2+ph)%1)));if(r>2)star(c,x,y,r)}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// milk carton tipping to pour into a glass that fills up, then a straw sips it back down for the loop
|
||||
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 glass=c=>{c.beginPath();c.moveTo(160,140);c.lineTo(168,226);c.quadraticCurveTo(169,232,175,232);c.lineTo(213,232);c.quadraticCurveTo(219,232,220,226);c.lineTo(228,140)}
|
||||
export default(c,t)=>{
|
||||
const a=1.05*(ease(t/.18)-ease((t-.55)/.15)),pour=a>.85,L=.78*(ease((t-.17)/.4)-ease((t-.68)/.22)),ly=230-88*L
|
||||
const C=[88,112],sp=[C[0]+34*cos(a)+42*sin(a),C[1]+34*sin(a)-42*cos(a)]
|
||||
c.lineWidth=4;for(const x of[172,180])c.beginPath(),c.moveTo(x,166),c.lineTo(x+4,196),c.stroke()
|
||||
if(L>.01){c.save();glass(c);c.clip();c.beginPath();c.moveTo(150,240);c.lineTo(150,ly);for(let x=150;x<=240;x+=3)c.lineTo(x,ly+(pour?2.5*sin(x/7-t*T*6):0));c.lineTo(240,240);c.fill();c.lineWidth=5;c.stroke();c.restore()}
|
||||
const st=t>=.62&&t<.96?min(1,(t-.62)/.06,(.96-t)/.06):0
|
||||
if(st>0){const o=(1-st)*70;for(const[w,s]of[[15,'#111'],[7,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(246+o*.4,70-o),c.lineTo(226+o*.4,100-o),c.lineTo(196+o*.4,214-o),c.stroke()}
|
||||
for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,glass(c),c.stroke()
|
||||
if(pour)for(const[w,s]of[[14,'#111'],[6,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(...sp),c.quadraticCurveTo(sp[0]+40,sp[1]-4,194,ly),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.save();c.translate(...C);c.rotate(a)
|
||||
c.beginPath();c.roundRect(-12,-72,24,12,3);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(-36,64);c.lineTo(-36,-38);c.lineTo(0,-64);c.lineTo(36,-38);c.lineTo(36,64);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(-36,-38);c.lineTo(36,-38);c.stroke()
|
||||
if(pour)for(const x of[-14,14])c.beginPath(),c.arc(x,8,7,PI*1.15,PI*1.85),c.stroke()
|
||||
else{c.fillStyle='#111';for(const x of[-14,14])c.beginPath(),c.ellipse(x,6,5,7,0,0,T),c.fill();c.fillStyle='#fff';for(const x of[-16,12])c.beginPath(),c.arc(x,3,2,0,T),c.fill()}
|
||||
c.beginPath();c.arc(0,16,9,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=3;for(const d of[-1,1])for(const o of[-5,0,5])c.beginPath(),c.moveTo(d*24+o-2,30),c.lineTo(d*24+o+2,23),c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(0,40);c.quadraticCurveTo(9,52,0,56);c.quadraticCurveTo(-9,52,0,40);c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// monkey swinging from a vine by one arm and waving with the other, its legs and tail lagging behind
|
||||
// drawn at Z times the base size, so line widths are divided by Z to stay at the usual ink weight
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=85
|
||||
const Z=1.6,W=x=>x/Z
|
||||
export default(c,t)=>{
|
||||
const a=.12*sin(T*t),lg=-.22*cos(T*t),wv=sin(2*T*t)
|
||||
const dbl=(f,core,o=12)=>{c.beginPath();f();for(const[l,s]of[[core+W(o),'#111'],[core,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.stroke();c.strokeStyle='#111';c.lineWidth=W(7)}
|
||||
c.translate(130,-64);c.rotate(a)
|
||||
for(const[l,s]of[[13,'#111'],[5,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(0,0),c.quadraticCurveTo(5,40,0,84),c.stroke()
|
||||
c.translate(0,86);c.scale(Z,Z);c.translate(0,-86);c.strokeStyle='#111';c.lineWidth=W(7)
|
||||
c.save();c.translate(14,198);c.rotate(lg)
|
||||
dbl(()=>{c.moveTo(0,0);c.bezierCurveTo(30,14,40,-20,28,-28);c.quadraticCurveTo(18,-32,20,-20)},5,8)
|
||||
for(const x of[-14,6])dbl(()=>{c.moveTo(x,0);c.lineTo(x-3,14)},12)
|
||||
for(const x of[-17,3])c.beginPath(),c.ellipse(x,18,11,6.5,0,0,T),c.fill(),c.stroke()
|
||||
c.restore()
|
||||
dbl(()=>{c.moveTo(12,150);c.lineTo(2,90)},12)
|
||||
c.beginPath();c.arc(0,88,9,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(6,178,26,28,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=W(5);c.beginPath();c.ellipse(4,184,14,16,0,0,T);c.stroke();c.lineWidth=W(7)
|
||||
const hx=-38+4*wv,hy=190-8*wv
|
||||
dbl(()=>{c.moveTo(-6,166);c.lineTo(hx,hy)},12)
|
||||
c.beginPath();c.arc(hx-3,hy+2,9,0,T);c.fill();c.stroke()
|
||||
for(const[x,y]of[[-52,136],[10,128]]){
|
||||
c.beginPath();c.arc(x,y,10,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=W(4);c.beginPath();c.arc(x,y,4,0,T);c.stroke();c.lineWidth=W(7)
|
||||
}
|
||||
c.beginPath();c.arc(-21,134,31,0,T);c.fill();c.stroke()
|
||||
const face=[()=>c.arc(-30,130,11.5,0,T),()=>c.arc(-12,130,11.5,0,T),()=>c.ellipse(-21,147,16,11,0,0,T)]
|
||||
c.lineWidth=W(5);for(const f of face)c.beginPath(),f(),c.stroke();for(const f of face)c.beginPath(),f(),c.fill()
|
||||
c.fillStyle='#111';for(const x of[-29,-13])c.beginPath(),c.arc(x,131,4.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[-30,-14])c.beginPath(),c.arc(x,129.5,1.6,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const x of[-24,-18])c.beginPath(),c.arc(x,143,1.6,0,T),c.fill()
|
||||
c.lineWidth=W(4);c.beginPath();c.arc(-21,148,7.5,.15*PI,.85*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// mouse sitting up and sniffing: nose twitching, whiskers wiggling, an ear flicking and its tail curling
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const delay=70
|
||||
export default(c,t)=>{
|
||||
const sn=t<.5?sin(8*T*t):0,tw=2*sn,ef=t>.6&&t<.8?sin(PI*(t-.6)/.2):0,tc=sin(T*t)
|
||||
for(const[l,s]of[[15,'#111'],[6,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(160,214),c.bezierCurveTo(206,232,238,204,226,170+6*tc),c.quadraticCurveTo(216,142+8*tc,198,152+6*tc),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.ellipse(128,182,50,46,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.ellipse(128,194,28,24,0,0,T);c.stroke();c.lineWidth=7
|
||||
for(const x of[104,152])c.beginPath(),c.ellipse(x,226,19,9,0,0,T),c.fill(),c.stroke()
|
||||
for(const d of[-1,1]){
|
||||
c.save();c.translate(128+d*26,96);c.rotate(d>0?.35*ef:0)
|
||||
c.beginPath();c.arc(d*20,-26,30,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(d*20,-26,16,0,T);c.stroke();c.lineWidth=7;c.restore()
|
||||
}
|
||||
c.beginPath();c.arc(128,112,46,0,T);c.fill();c.stroke()
|
||||
for(const x of[112,144])c.beginPath(),c.arc(x,166,10,0,T),c.fill(),c.stroke()
|
||||
for(const d of[-1,1])for(const a of[-.24,0,.24]){
|
||||
const x=128+d*16,y=132+tw*.5,e=(d>0?0:PI)+d*(a+.1*sn)
|
||||
for(const[l,s]of[[7,'#111'],[2.5,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(x,y),c.lineTo(x+46*cos(e),y+46*sin(e)),c.stroke()
|
||||
}
|
||||
c.strokeStyle='#111';c.fillStyle='#111'
|
||||
for(const x of[110,146])c.beginPath(),c.arc(x,106,7,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[108,144])c.beginPath(),c.arc(x,103,2.5,0,T),c.fill()
|
||||
c.lineWidth=3;c.beginPath();c.rect(123,145,10,9);c.fill();c.stroke();c.beginPath();c.moveTo(128,145);c.lineTo(128,154);c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(128,128+tw);c.lineTo(128,139);c.arc(122,139,6,0,PI);c.moveTo(140,139);c.arc(134,139,6,0,PI);c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(128,127+tw,8,6,0,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// key slides into a padlock and turns, the shackle pops up and swings round on its right leg, then it all closes and the key slides out
|
||||
// the swing is a horizontal squash about the right leg, so the shackle seems to turn in depth
|
||||
const{sin,cos,PI,min,max,abs}=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 dx=26*(1-ease(t/.16))+26*ease((t-.88)/.12),turn=ease((t-.16)/.12)-ease((t-.76)/.12)
|
||||
const up=ease((t-.28)/.1)-ease((t-.68)/.1),sw=2.4*(ease((t-.36)/.14)-ease((t-.54)/.14))
|
||||
c.save();c.translate(148,-22*up);c.scale(cos(sw),1);c.translate(-148,0)
|
||||
for(const[w,k]of[[34,'#111'],[20,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(72,150),c.lineTo(72,84),c.arc(110,84,38,PI,0),c.lineTo(148,150),c.stroke()
|
||||
c.restore()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.roundRect(40,122,140,110,18);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(54,138);c.lineTo(166,138);c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(110,170,11,0,T);c.moveTo(104,174);c.lineTo(101,204);c.lineTo(119,204);c.lineTo(116,174);c.fill()
|
||||
if(up>.6&&sw<.3)for(const a of[-2.4,-1.9,-1.4])for(const[w,k]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(64+cos(a)*30,108+sin(a)*30),c.lineTo(64+cos(a)*44,108+sin(a)*44),c.stroke()
|
||||
const k=max(.3,abs(cos(turn*PI/2)))
|
||||
c.save();c.translate(dx,172);c.scale(1,k);c.lineWidth=7;c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
c.beginPath();c.roundRect(106,-9,84,18,6);c.fill();c.stroke()
|
||||
c.lineWidth=5;for(const x of[136,152])c.beginPath(),c.moveTo(x,-9),c.lineTo(x,9),c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.arc(204,0,24,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(208,0,8,0,T);c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// pigeon walking in place: its head jerks forward and holds while the body catches up, feet stepping in turn
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
export default(c,t)=>{
|
||||
const q=(2*t)%1,s=q/.25,e=q<.25?s*s*(3-2*s):1-(q-.25)/.75,hx=-6+18*e,hy=-3*sin(PI*e),by=12+1.5*cos(4*PI*t)
|
||||
for(const j of[0,1]){
|
||||
const l=max(0,sin(T*t+j*PI)),fx=100+j*24+8*l,fy=234-10*l
|
||||
for(const[w,st]of[[11,'#111'],[4,'#fff']]){
|
||||
c.lineWidth=w;c.strokeStyle=st;c.beginPath()
|
||||
c.moveTo(104+j*20,180+by);c.lineTo(fx,fy);c.moveTo(fx-8,fy);c.lineTo(fx+14,fy);c.moveTo(fx,fy);c.lineTo(fx+12,fy+5)
|
||||
c.stroke()
|
||||
}
|
||||
}
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.beginPath();c.moveTo(74,136+by);c.lineTo(20,160+by);c.lineTo(26,180+by);c.lineTo(78,164+by);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(36,156+by);c.lineTo(42,174+by);c.moveTo(48,151+by);c.lineTo(54,170+by);c.stroke()
|
||||
const hd=()=>{c.beginPath();c.arc(160+hx,84+hy+by,21,0,T)},bd=()=>{c.beginPath();c.ellipse(110,146+by,58,42,-.12,0,T)},nk=()=>{c.beginPath();c.moveTo(134,128+by);c.lineTo(150+hx*.7,98+hy+by)}
|
||||
c.lineWidth=14;bd();c.stroke();hd();c.stroke();c.lineWidth=44;nk();c.stroke()
|
||||
bd();c.fill();hd();c.fill();c.lineWidth=30;c.strokeStyle='#fff';nk();c.stroke();c.strokeStyle='#111'
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(80,128+by);c.quadraticCurveTo(140,118+by,150,156+by);c.quadraticCurveTo(116,182+by,62,150+by);c.stroke()
|
||||
c.fillStyle='#111';for(const x of[100,120])c.beginPath(),c.moveTo(x,134+by),c.lineTo(x+8,132+by),c.lineTo(x+20,160+by),c.lineTo(x+12,163+by),c.closePath(),c.fill()
|
||||
c.lineWidth=4;for(const r of[24,32])c.beginPath(),c.arc(130+hx*.4,104+by+hy*.5,r,-.2*PI,.25*PI),c.stroke()
|
||||
const X=160+hx,Y=84+hy+by
|
||||
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.moveTo(176+hx,80+hy+by);c.lineTo(197+hx,88+hy+by);c.lineTo(177+hx,93+hy+by);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=3;c.beginPath();c.ellipse(X+18,Y-5,5,4,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(X+6,Y-4,6,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(X+7,Y-4,3,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// custard pudding on a plate wobbling and jiggling, the caramel on top shining
|
||||
// the whole pudding gets a white rim so the black caramel shows on dark backgrounds
|
||||
const{sin,exp,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const body=c=>{c.beginPath();c.moveTo(-66,0);c.lineTo(-46,-94);c.quadraticCurveTo(0,-108,46,-94);c.lineTo(66,0);c.quadraticCurveTo(0,8,-66,0);c.closePath()}
|
||||
export default(c,t)=>{
|
||||
c.beginPath();c.ellipse(128,214,100,20,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(128,212,74,12,0,0,T);c.stroke();c.lineWidth=7
|
||||
const k=.16*sin(2*T*t),sy=1+.05*sin(4*T*t+.6)
|
||||
c.save();c.translate(128,212);c.transform(1,0,k,sy,0,0)
|
||||
body(c);c.lineWidth=16;c.strokeStyle='#fff';c.stroke();c.fill()
|
||||
c.save();body(c);c.clip();c.fillStyle='#111';c.beginPath();c.moveTo(-90,-130);c.lineTo(90,-130)
|
||||
for(let x=90;x>=-90;x-=2)c.lineTo(x,-82+[[-48,12],[-22,22],[4,10],[28,18],[52,9]].reduce((y,[d,L])=>y+L*exp(-(((x-d)/6)**2)),0))
|
||||
c.closePath();c.fill();c.restore()
|
||||
c.lineWidth=7;c.strokeStyle='#111';body(c);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.moveTo(-32,-94);c.quadraticCurveTo(-20,-100,-6,-100);c.stroke();c.strokeStyle='#111'
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(d*18,-42,5.5,7.5,0,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(d*18-2,-45,2.2,0,T),c.fill()
|
||||
c.lineWidth=4.5;c.beginPath();c.arc(0,-32,9,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=3;for(const d of[-1,1])for(const o of[-5,0,5])c.beginPath(),c.moveTo(d*38+o-2,-24),c.lineTo(d*38+o+2,-32),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// two jigsaw pieces slide together and snap into place with a click spark, grin about it, then drift apart
|
||||
const{sin,cos,PI,atan2,max}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
// one side from (x1,y1) to (x2,y2) with a round tab (k=1) or slot (k=-1) in the middle; outward is to the left of travel
|
||||
const side=(c,x1,y1,x2,y2,k)=>{
|
||||
const l=Math.hypot(x2-x1,y2-y1),dx=(x2-x1)/l,dy=(y2-y1)/l,nx=dy*k,ny=-dx*k,mx=(x1+x2)/2,my=(y1+y2)/2
|
||||
const cx=mx+nx*13,cy=my+ny*13,a1=atan2(my-dy*9-cy,mx-dx*9-cx),a2=atan2(my+dy*9-cy,mx+dx*9-cx),ao=atan2(ny,nx)
|
||||
const cw=((ao-a1)%T+T)%T<((a2-a1)%T+T)%T
|
||||
c.lineTo(mx-dx*9,my-dy*9);c.arc(cx,cy,15.8,a1,a2,!cw);c.lineTo(x2,y2)
|
||||
}
|
||||
const face=(c,x,happy,look)=>{
|
||||
c.fillStyle='#111';c.lineWidth=5
|
||||
for(const d of[-1,1]){
|
||||
if(happy)c.beginPath(),c.arc(x+d*12,2,7,PI*1.1,PI*1.9),c.stroke()
|
||||
else c.beginPath(),c.ellipse(x+d*12+look,0,5,7,0,0,T),c.fill()
|
||||
}
|
||||
if(happy){c.lineWidth=3;for(const d of[-1,1])for(const o of[-4,0,4])c.beginPath(),c.moveTo(x+d*20+o-2,16),c.lineTo(x+d*20+o+2,10),c.stroke()}
|
||||
c.lineWidth=4;c.beginPath();c.arc(x,10,happy?8:5,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=7;c.fillStyle='#fff'
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const g=t<.35?22*(1-(t/.35)**2):t<.7?0:22*(1-cos(PI*(t-.7)/.3))/2,on=t>=.35&&t<.7,j=on&&t<.45?3*sin((t-.35)*80):0
|
||||
c.translate(128,128);c.scale(1.12,1.12);c.translate(-128,-128)
|
||||
if(t>=.35&&t<.52){const k=sin(PI*(t-.35)/.17);for(const a of[-.9,-.45,.45,.9])D(c,()=>{c.moveTo(128+sin(a)*20*k,90-cos(a)*20*k);c.lineTo(128+sin(a)*44*k,90-cos(a)*44*k)})}
|
||||
c.save();c.translate(128-g,128+j)
|
||||
c.beginPath();c.moveTo(-76,-38);side(c,-76,-38,0,-38,1);side(c,0,-38,0,38,1);c.lineTo(-76,38);c.closePath();c.fill();c.stroke()
|
||||
face(c,-38,on,g>4?4:0);c.restore()
|
||||
c.save();c.translate(128+g,128+j)
|
||||
c.beginPath();c.moveTo(0,-38);c.lineTo(76,-38);c.lineTo(76,38);side(c,76,38,0,38,1);side(c,0,38,0,-38,-1);c.closePath();c.fill();c.stroke()
|
||||
face(c,42,on,g>4?-4:0);c.restore()
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// big question mark bouncing and tilting curiously while its dot hops along on its own beat
|
||||
const{sin,PI,abs}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
export default(c,t)=>{
|
||||
const j=30*abs(sin(PI*t)),sq=j<5,dj=24*abs(sin(2*PI*t))
|
||||
c.save();c.translate(128,184-j);c.rotate(.16*sin(t*T));if(sq)c.scale(1.1,.9);c.translate(-128,-184)
|
||||
for(const[w,s]of[[48,'#111'],[34,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.arc(128,82,40,PI,PI*2.3);c.quadraticCurveTo(128,126,128,148);c.lineTo(128,158);c.stroke()}
|
||||
c.restore()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.ellipse(128,212-dj,dj<4?22:19,dj<4?16:19,0,0,T);c.fill();c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// scissors snipping open and shut twice, with a little spark at the tips each time they close
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t)=>{
|
||||
const o=.5+.5*cos(2*T*t),th=.03+.3*o
|
||||
c.translate(140,122);c.rotate(-.75)
|
||||
for(const s of[1,-1]){
|
||||
c.save();c.rotate(s*th)
|
||||
for(const[w,k]of[[30,'#111'],[16,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(0,0),c.quadraticCurveTo(-28,-s*4,-50,-s*22),c.stroke(),c.beginPath(),c.arc(-72,-s*36,24,0,T),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.moveTo(-10,-s*14);c.quadraticCurveTo(50,-s*18,112,0);c.quadraticCurveTo(50,s*4,-10,s*8);c.closePath();c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
c.beginPath();c.arc(0,0,10,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(0,0,3.5,0,T);c.fill();c.fillStyle='#fff'
|
||||
const sp=max(0,1-o*4)
|
||||
if(sp>0)for(const a of[-1,0,1])for(const[w,k]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(116+cos(a)*12,sin(a)*12),c.lineTo(116+cos(a)*(12+16*sp),sin(a)*(12+16*sp)),c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// seal balancing a ball on its nose, the ball rolling side to side while its flippers clap
|
||||
const{sin,cos,PI,atan2}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t)=>{
|
||||
const bx=11*sin(t*T),cl=(1-cos(2*T*t))/2,ph=.15+1.75*cl
|
||||
const flip=(px,py,L)=>{const dx=sin(ph),dy=cos(ph);c.beginPath();c.ellipse(px+dx*L/2,py+dy*L/2,10,L/2+4,atan2(dy,dx)-PI/2,0,T);c.fill();c.stroke()}
|
||||
for(const[x,y,r]of[[50,212,-.9],[44,234,-.3]])c.beginPath(),c.ellipse(x,y,22,10,r,0,T),c.fill(),c.stroke()
|
||||
flip(150,166,40)
|
||||
const parts=[[112,196,66,40,-.35],[148,150,26,38,-.35],[158,112,30,26,-.95],[180,88,17,12,-.95]]
|
||||
c.lineWidth=14;for(const[x,y,rx,ry,r]of parts)c.beginPath(),c.ellipse(x,y,rx,ry,r,0,T),c.stroke()
|
||||
for(const[x,y,rx,ry,r]of parts)c.beginPath(),c.ellipse(x,y,rx,ry,r,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(150,186);c.quadraticCurveTo(130,226,74,222);c.stroke()
|
||||
c.fillStyle='#111';for(const[x,y]of[[96,176],[84,190],[104,194]])c.beginPath(),c.arc(x,y,3.5,0,T),c.fill()
|
||||
c.beginPath();c.ellipse(164,104,6,8,-.3,0,T);c.fill();c.beginPath();c.ellipse(189,76,6,5,-.95,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(162,101,2.2,0,T);c.fill()
|
||||
c.fillStyle='#111';for(const[x,y]of[[176,92],[182,96],[172,98]])c.beginPath(),c.arc(x,y,1.8,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(178,104);c.quadraticCurveTo(186,102,192,94);c.stroke()
|
||||
c.lineWidth=7;c.fillStyle='#fff';flip(136,174,46)
|
||||
if(cl>.8)for(const a of[-.6,0,.6])for(const[l,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(196+cos(a)*14,156+sin(a)*14),c.lineTo(196+cos(a)*26,156+sin(a)*26),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
const x=190+bx,y=50+bx*bx/60
|
||||
c.beginPath();c.arc(x,y,26,0,T);c.fill();c.stroke()
|
||||
c.save();c.translate(x,y);c.rotate(bx/26);c.fillStyle='#111'
|
||||
c.beginPath();c.arc(0,0,23,0,T);c.clip();c.beginPath();c.ellipse(0,0,9,30,0,0,T);c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(0,0,19,30,0,0,T);c.stroke();c.restore()
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// shark fin circling round a pool of water, bigger as it passes in front, a little wake trailing behind
|
||||
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
export default(c,t)=>{
|
||||
c.beginPath();for(let k=0;k<=120;k++){const a=k/120*T,r=1+.025*sin(a*16);c.lineTo(128+114*r*cos(a),150+74*r*sin(a))}
|
||||
c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(128,150,96,60,0,0,T);c.stroke()
|
||||
const a=t*T+PI/2,x=128+62*cos(a),y=158+36*sin(a),dir=sin(a)>0?-1:1,d=.75+.25*sin(a),sx=dir*(.4+.6*abs(sin(a)))*d*1.3,sy=d*1.3
|
||||
const P=(px,py)=>[x+px*sx,y+py*sy]
|
||||
c.lineWidth=4;c.beginPath()
|
||||
for(const s of[-1,1])c.moveTo(...P(-26,0)),c.quadraticCurveTo(...P(-40,5*s),...P(-58,4+8*s))
|
||||
c.stroke()
|
||||
c.beginPath();c.moveTo(...P(-22,0));c.quadraticCurveTo(...P(-6,-28),...P(-20,-64));c.quadraticCurveTo(...P(16,-46),...P(30,0));c.closePath()
|
||||
c.lineWidth=7;c.fillStyle='#111';c.fill();c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=4;c.beginPath();c.moveTo(...P(14,-8));c.quadraticCurveTo(...P(8,-30),...P(-8,-46));c.stroke()
|
||||
c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
// fluffy sheep hopping in place, its wool squashing on landing and stretching in the air
|
||||
// the wool is one outline: every puff is stroked wide first, then all of them are filled
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const delay=60
|
||||
export default(c,t)=>{
|
||||
const air=t>=.25,a=(t-.25)/.75,h=air?70*4*a*(1-a):0,g=air?0:sin(PI*t/.25),st=air?.08*(1-4*a*(1-a)):0
|
||||
const sx=1+.16*g-.4*st,sy=1-.16*g+st
|
||||
const wool=(L,r)=>{c.lineWidth=14;c.strokeStyle='#111';for(const[x,y]of L)c.beginPath(),c.arc(x,y,r,0,T),c.stroke();c.fillStyle='#fff';for(const[x,y]of L)c.beginPath(),c.arc(x,y,r,0,T),c.fill()}
|
||||
const dark=f=>{c.beginPath();f();c.lineWidth=14;c.strokeStyle='#fff';c.stroke();c.fillStyle='#111';c.fill()}
|
||||
c.save();c.translate(128,232-h);c.scale(sx,sy)
|
||||
for(const x of[-38,-14,14,38])for(const[l,s]of[[22,'#fff'],[12,'#111']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(x,-50),c.lineTo(x,-6),c.stroke()
|
||||
wool([...Array(14)].map((_,i)=>[66*cos(i*T/14),-90+40*sin(i*T/14)]),22)
|
||||
c.beginPath();c.ellipse(0,-90,66,40,0,0,T);c.fill()
|
||||
for(const d of[-1,1])dark(()=>c.ellipse(d*34,-92,20,9,d*.45,0,T))
|
||||
dark(()=>c.ellipse(0,-76,27,33,0,0,T))
|
||||
wool([[-13,-104],[0,-111],[13,-104]],12)
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(d*11,-80,8,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*10,-79,4.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(d*10-1.5,-81,1.6,0,T),c.fill()
|
||||
c.strokeStyle='#fff';c.lineWidth=3;c.beginPath();c.moveTo(-8,-60);c.quadraticCurveTo(-4,-54,0,-59);c.quadraticCurveTo(4,-54,8,-60);c.stroke()
|
||||
c.restore();c.strokeStyle='#111';c.lineWidth=7;c.fillStyle='#fff'
|
||||
if(g>.2)for(const s of[-1,1])c.beginPath(),c.arc(128+s*(100+12*g),226,9*g,0,T),c.fill(),c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// cute skull bobbing along while its jaw chatters open and shut
|
||||
const{sin,PI,abs}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
const teeth=(c,y,h)=>{c.lineWidth=4;for(const x of[104,116,128,140,152])c.beginPath(),c.roundRect(x-6,y,12,h,3),c.fill(),c.stroke();c.lineWidth=7}
|
||||
export default(c,t)=>{
|
||||
const o=12*abs(sin(4*PI*t)),b=4*sin(t*T)
|
||||
if(o<4)for(const d of[-1,1])for(const y of[-12,0,12])D(c,()=>{c.moveTo(128+d*(74+(y?0:6)),186+y);c.lineTo(128+d*94,186+y)})
|
||||
c.translate(128,140+b);c.rotate(.05*sin(t*T));c.translate(-128,-140)
|
||||
c.beginPath();c.moveTo(92,182+o);c.lineTo(164,182+o);c.quadraticCurveTo(166,214+o,128,216+o);c.quadraticCurveTo(90,214+o,92,182+o);c.fill();c.stroke()
|
||||
teeth(c,172+o,14)
|
||||
const sk=()=>{c.beginPath();c.ellipse(128,94,76,68,0,0,T)},up=()=>{c.beginPath();c.roundRect(86,110,84,52,16)}
|
||||
c.lineWidth=14;sk();c.stroke();up();c.stroke();sk();c.fill();up();c.fill();c.lineWidth=7
|
||||
teeth(c,158,14)
|
||||
c.fillStyle='#111'
|
||||
for(const x of[100,156])c.beginPath(),c.ellipse(x,106,20,22,0,0,T),c.fill()
|
||||
c.beginPath();c.moveTo(128,128);c.lineTo(119,143);c.quadraticCurveTo(128,147,137,143);c.closePath();c.fill()
|
||||
c.fillStyle='#fff';for(const x of[100,156])c.beginPath(),c.arc(x-6,99,6,0,T),c.fill(),c.beginPath(),c.arc(x+6,114,2.5,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(150,30);c.lineTo(156,44);c.lineTo(148,52);c.lineTo(154,62);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// sloth hanging from a branch by its arms, slowly swaying and taking a long sleepy blink
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=100
|
||||
export default(c,t)=>{
|
||||
const a=.07*sin(T*t),bl=t>.5&&t<.8
|
||||
const dbl=(f,b,w)=>{c.beginPath();f();for(const[l,s]of[[b,'#111'],[w,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.stroke();c.strokeStyle='#111';c.lineWidth=7}
|
||||
for(const[x,r]of[[34,-.5],[222,.5]])c.beginPath(),c.ellipse(x,30,16,8,r,0,T),c.fill(),c.stroke()
|
||||
c.beginPath();c.roundRect(12,38,232,24,12);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const x of[40,196,220])c.beginPath(),c.moveTo(x,46),c.quadraticCurveTo(x+8,50,x+14,46),c.stroke();c.lineWidth=7
|
||||
c.translate(128,50);c.rotate(a);c.translate(-128,-50)
|
||||
for(const d of[-1,1])dbl(()=>{c.moveTo(128+d*24,212);c.quadraticCurveTo(128+d*36,232,128+d*30,240)},26,14)
|
||||
for(const d of[-1,1])dbl(()=>{c.moveTo(128+d*34,152);c.lineTo(128+d*36,56)},30,18)
|
||||
c.lineWidth=5
|
||||
for(const d of[-1,1])for(const o of[-8,0,8])c.beginPath(),c.moveTo(128+d*36+o,58),c.quadraticCurveTo(128+d*36+o+9,40,128+d*36+o-1,34),c.stroke()
|
||||
c.lineWidth=7
|
||||
c.beginPath();c.ellipse(128,182,46,50,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const y of[180,196,212])c.beginPath(),c.arc(128,y-30,26,.35*PI,.65*PI),c.stroke();c.lineWidth=7
|
||||
c.beginPath();c.arc(128,130,40,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(128,138,30,24,0,0,T);c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*15,136,12,6.5,d*.45,0,T),c.fill()
|
||||
c.fillStyle='#fff';c.strokeStyle='#fff'
|
||||
for(const d of[-1,1])if(bl)c.lineWidth=2.5,c.beginPath(),c.arc(128+d*14,134,4,.15*PI,.85*PI),c.stroke()
|
||||
else{c.beginPath();c.arc(128+d*14,135,4.5,0,T);c.fill();c.fillStyle='#111';c.beginPath();c.arc(128+d*14,135.5,2.8,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(128+d*14-1,134,1,0,T);c.fill()}
|
||||
c.strokeStyle='#111';c.fillStyle='#111';c.beginPath();c.ellipse(128,148,7,5,0,0,T);c.fill()
|
||||
c.lineWidth=3.5;c.beginPath();c.arc(128,149,9,.2*PI,.8*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// snowman waving a twig arm and tipping its top hat while snowflakes drift past
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const flake=(c,x,y,r)=>{for(const[w,s]of[[9,'#111'],[3,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();for(let k=0;k<3;k++){const a=k*PI/3;c.moveTo(x-cos(a)*r,y-sin(a)*r);c.lineTo(x+cos(a)*r,y+sin(a)*r)}c.stroke()}}
|
||||
const twig=(c,x0,y0,a,L)=>{
|
||||
const x1=x0+cos(a)*L,y1=y0+sin(a)*L
|
||||
for(const[w,s]of[[11,'#111'],[4,'#fff']]){
|
||||
c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.moveTo(x0,y0);c.lineTo(x1,y1)
|
||||
for(const d of[-.6,.6])c.moveTo(x0+cos(a)*L*.7,y0+sin(a)*L*.7),c.lineTo(x0+cos(a)*L*.7+cos(a+d)*16,y0+sin(a)*L*.7+sin(a+d)*16)
|
||||
c.moveTo(x1,y1);c.lineTo(x1+cos(a-.5)*12,y1+sin(a-.5)*12);c.moveTo(x1,y1);c.lineTo(x1+cos(a+.5)*12,y1+sin(a+.5)*12);c.stroke()
|
||||
}
|
||||
c.strokeStyle='#111'
|
||||
}
|
||||
export default(c,t)=>{
|
||||
for(const[x,o]of[[30,0],[226,.4],[206,.75]]){const p=(t+o)%1;if(p>.08&&p<.92)flake(c,x+6*sin(p*T),p*130+18,8*sin(PI*p))}
|
||||
twig(c,100,140,PI+.45,58);twig(c,156,140,-.75+.4*sin(2*T*t),58)
|
||||
const B=[[128,204,46],[128,140,34],[128,86,26]]
|
||||
c.lineWidth=14;for(const[x,y,r]of B)c.beginPath(),c.arc(x,y,r,0,T),c.stroke()
|
||||
for(const[x,y,r]of B)c.beginPath(),c.arc(x,y,r,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const y of[126,144,162])c.beginPath(),c.arc(128,y,4.5,0,T),c.fill()
|
||||
for(const x of[118,138])c.beginPath(),c.arc(x,78,4.5,0,T),c.fill()
|
||||
for(const k of[-2,-1,0,1,2])c.beginPath(),c.arc(128+k*7,100-Math.abs(k)*2,2.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';c.lineWidth=5;c.beginPath();c.moveTo(128,84);c.lineTo(156,90);c.lineTo(128,93);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=3;c.beginPath();c.moveTo(138,86);c.lineTo(136,91);c.moveTo(146,88);c.lineTo(144,91);c.stroke()
|
||||
const sw=3*sin(T*t)
|
||||
c.lineWidth=6;c.beginPath();c.moveTo(146,110);c.quadraticCurveTo(152+sw,130,150+sw,146);c.lineTo(138+sw,146);c.quadraticCurveTo(142,128,136,110);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(98,106,60,14,7);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();for(const x of[112,128,144])c.moveTo(x,108),c.lineTo(x,118);c.moveTo(140+sw,134);c.lineTo(150+sw,134);c.stroke()
|
||||
const l=max(0,sin(T*t))**2
|
||||
c.save();c.translate(150,64);c.rotate(-.35*l);c.translate(-150,-64-10*l)
|
||||
const dark=f=>{c.beginPath();f();c.lineWidth=16;c.strokeStyle='#fff';c.stroke();c.fillStyle='#111';c.fill();c.lineWidth=7;c.strokeStyle='#111';c.stroke()}
|
||||
dark(()=>c.roundRect(110,26,36,36,4));dark(()=>c.ellipse(128,62,32,7,0,0,T))
|
||||
c.fillStyle='#fff';c.fillRect(110,48,36,7);c.restore()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// spider bouncing on its thread like a bungee cord, legs wiggling
|
||||
// legs and body get their white rims in one pass first, so they read on black
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const delay=70
|
||||
export default(c,t)=>{
|
||||
const y=132+32*sin(T*t)
|
||||
for(const[l,s]of[[6,'#111'],[2,'#fff']])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),c.moveTo(128,0),c.lineTo(128,y-20),c.stroke()
|
||||
const legs=[]
|
||||
for(const d of[-1,1])for(let i=0;i<4;i++){
|
||||
const wg=6*sin(2*T*t+i*1.3+(d>0?1:0)),by=y-9+i*7
|
||||
legs.push([[128+d*18,by],[128+d*(50+i*3),y-30+i*14+wg*.5],[128+d*(70-i*2),y-10+i*20+wg]])
|
||||
}
|
||||
const pl=p=>{c.beginPath();c.moveTo(...p[0]);c.lineTo(...p[1]);c.lineTo(...p[2])}
|
||||
c.strokeStyle='#fff';c.lineWidth=15;for(const p of legs)pl(p),c.stroke()
|
||||
c.lineWidth=16;c.beginPath();c.ellipse(128,y,30,27,0,0,T);c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7;for(const p of legs)pl(p),c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(128,y,30,27,0,0,T);c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*11,y-4,8,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*10,y-2,4.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*10-1.5,y-4,1.5,0,T),c.fill()
|
||||
c.strokeStyle='#fff';c.lineWidth=3;c.beginPath();c.arc(128,y+8,6,.15*PI,.85*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// spring toy squashes down, boings up into the air stretched and wobbling, then lands and settles
|
||||
const{sin,cos,PI,max,min}=Math,T=2*PI
|
||||
export const frames=24,delay=60
|
||||
const N=4,R=40,E=11
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
export default(c,t)=>{
|
||||
const sq=t<.3,air=!sq&&t<.8,a=(t-.3)/.5
|
||||
const L=sq?100-50*(t/.3)**2:air?100+30*(1-a)*cos(3*PI*a):100-16*sin(PI*(t-.8)/.2),J=air?44*4*a*(1-a):0
|
||||
const yb=212-J,yt=yb-L,hy=yt-28,k=1-J/110
|
||||
D(c,()=>{c.moveTo(128-46*k,232);c.lineTo(128+46*k,232)})
|
||||
c.beginPath();c.ellipse(128,yb+8,50,13,0,0,PI);c.lineTo(78,yb);c.ellipse(128,yb,50,13,0,PI,0,true);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(128,yb,50,13,0,0,T);c.fill();c.stroke()
|
||||
// the coil: back half-turns first, then the front ones over them
|
||||
const P=th=>[128+R*sin(th),yb-L*th/(N*T)+E*cos(th)]
|
||||
for(const f of[1,0])for(let k=f;k<=2*N;k+=2){
|
||||
const a0=max(0,(k-.5)*PI),a1=min(N*T,(k+.5)*PI)
|
||||
D(c,()=>{for(let j=0;j<=12;j++){const[x,y]=P(a0+(a1-a0)*j/12);c.lineTo(x,y)}},14,5)
|
||||
}
|
||||
c.beginPath();c.ellipse(128,yt+4,30,9,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.arc(128,hy,30,0,T);c.fill();c.stroke()
|
||||
if(air&&a<.5)for(const d of[-1,1])D(c,()=>{for(let j=0;j<=6;j++)c.lineTo(128+d*(48+(j%2)*10),hy-24+j*8)})
|
||||
c.fillStyle='#111';c.lineWidth=5
|
||||
if(sq&&t>.08)for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*18,hy-10),c.lineTo(128+d*8,hy-4),c.lineTo(128+d*18,hy+2),c.stroke()
|
||||
else{for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*12,hy-4,5,7,0,0,T),c.fill();c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*12-2,hy-7,2,0,T),c.fill()}
|
||||
c.lineWidth=4;c.beginPath()
|
||||
if(air)c.ellipse(128,hy+12,5,6,0,0,T);else c.arc(128,hy+8,7,.15*PI,.85*PI)
|
||||
c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// squirrel sitting up nibbling an acorn in its paws, jaw working, crumbs falling, fluffy tail flicking
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t)=>{
|
||||
const ny=3*sin(4*T*t),open=sin(4*T*t)>0,tr=.06*sin(T*t)+.03*sin(2*T*t)
|
||||
c.save();c.translate(108,206);c.rotate(tr);c.translate(-108,-206)
|
||||
c.beginPath();c.moveTo(112,214);c.bezierCurveTo(40,220,20,150,38,104);c.bezierCurveTo(52,60,104,30,136,50)
|
||||
c.bezierCurveTo(112,56,88,74,84,104);c.bezierCurveTo(80,144,98,176,124,192);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const[x0,y0,x1,y1,x2,y2]of[[52,118,60,96,76,80],[48,160,56,140,62,128],[94,52,108,46,118,46]])c.beginPath(),c.moveTo(x0,y0),c.quadraticCurveTo(x1,y1,x2,y2),c.stroke()
|
||||
c.restore();c.lineWidth=7
|
||||
c.beginPath();c.moveTo(146,84);c.quadraticCurveTo(136,50,156,34);c.quadraticCurveTo(172,54,168,80);c.fill();c.stroke()
|
||||
const parts=[[134,168,38,48,.2],[118,208,34,28,0],[162,102,32,28,.25],[190,114,17,13,.3]]
|
||||
c.lineWidth=14;for(const[x,y,rx,ry,r]of parts)c.beginPath(),c.ellipse(x,y,rx,ry,r,0,T),c.stroke()
|
||||
for(const[x,y,rx,ry,r]of parts)c.beginPath(),c.ellipse(x,y,rx,ry,r,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(154,150);c.quadraticCurveTo(160,180,146,206);c.moveTo(96,196);c.quadraticCurveTo(112,184,132,190);c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.ellipse(150,236,22,8,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(168,94,6,8,.2,0,T);c.fill();c.beginPath();c.ellipse(205,110,5,4,0,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(166,91,2.2,0,T);c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(176,116,8+(open?2:0),.6*PI,1.6*PI);c.stroke()
|
||||
if(open){c.fillStyle='#111';c.beginPath();c.ellipse(197,124,5,4,0,0,T);c.fill();c.fillStyle='#fff';c.fillRect(194,120,6,4)}
|
||||
else c.beginPath(),c.moveTo(191,123),c.lineTo(202,121),c.stroke()
|
||||
for(const[w,s]of[[9,'#111'],[3,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.moveTo(204,114);c.lineTo(226,108);c.moveTo(204,118);c.lineTo(224,124);c.stroke()}
|
||||
c.strokeStyle='#111';c.fillStyle='#fff'
|
||||
const ax=187,ay=150+ny
|
||||
c.lineWidth=6;c.beginPath();c.ellipse(ax,ay+6,12,14,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(ax,ay-6,15,9,0,PI,T);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=3;c.save();c.beginPath();c.ellipse(ax,ay-6,15,9,0,PI,T);c.clip();for(let k=-3;k<=3;k++)c.beginPath(),c.moveTo(ax+k*7-8,ay-16),c.lineTo(ax+k*7+8,ay),c.moveTo(ax+k*7+8,ay-16),c.lineTo(ax+k*7-8,ay),c.stroke();c.restore()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(ax,ay-15);c.lineTo(ax+3,ay-22);c.stroke()
|
||||
for(const[w,s]of[[24,'#111'],[12,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(152,152),c.lineTo(174,158+ny),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5;for(const[x,y]of[[174,158],[200,156]])c.beginPath(),c.ellipse(x,y+ny,8,7,0,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=3;for(const k of[0,.5]){const p=(2*t+k)%1;c.beginPath();c.arc(182+k*16+4*sin(p*7),170+p*58,3.5,0,T);c.fill();c.stroke()}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// stapler chomping like a hungry mouth with a big eye, and on each bite a staple hops out the front and lands
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
export default(c,t)=>{
|
||||
const u=(t*2)%1,bite=u<.14?u/.14:u<.3?1-(u-.14)/.16:0,a=.5*(1-bite),p=(u-.16)/.5
|
||||
c.lineWidth=7
|
||||
c.beginPath();c.roundRect(20,198,212,32,16);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(170,186,40,16,5);c.fill();c.stroke()
|
||||
c.save();c.translate(50,186);c.rotate(-a)
|
||||
for(const[w,s]of[[30,'#fff'],[16,'#111']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(24,14),c.lineTo(160,14),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.moveTo(-18,-4);c.quadraticCurveTo(-18,-58,36,-60);c.lineTo(160,-50);c.quadraticCurveTo(184,-48,184,-22);c.lineTo(184,2);c.quadraticCurveTo(184,14,170,14);c.lineTo(4,14);c.quadraticCurveTo(-18,14,-18,-4);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(14,-34);c.lineTo(110,-30);c.stroke()
|
||||
if(bite>.5){c.lineWidth=6;c.beginPath();c.moveTo(140,-32);c.lineTo(152,-24);c.lineTo(140,-16);c.stroke()}
|
||||
else{c.lineWidth=6;c.beginPath();c.arc(150,-24,15,0,T);c.stroke();c.fillStyle='#111';c.beginPath();c.arc(153,-22,8,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(150,-25,3,0,T);c.fill()}
|
||||
c.restore()
|
||||
c.lineWidth=7;c.beginPath();c.arc(46,188,15,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(46,188,5,0,T);c.fill();c.fillStyle='#fff'
|
||||
if(p>0&&p<1){
|
||||
const x=220+14*p,y=176-80*4*p*(1-p)+20*p
|
||||
c.save();c.translate(x,y);c.rotate(p*T)
|
||||
for(const[w,k]of[[13,'#111'],[5,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(-12,8),c.lineTo(-12,-5),c.lineTo(12,-5),c.lineTo(12,8),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
if(bite>.6)for(const[x,y]of[[196,108],[220,112],[240,126]])for(const[w,k]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=k,c.beginPath(),c.moveTo(x-6,y+6),c.lineTo(x+4,y-4),c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// teapot tipping forward to pour a stream of tea into a cup, ripples on the cup, steam curling up
|
||||
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 P=[148,188],rot=(x,y,a)=>[P[0]+(x-P[0])*cos(a)-(y-P[1])*sin(a),P[1]+(x-P[0])*sin(a)+(y-P[1])*cos(a)]
|
||||
export default(c,t)=>{
|
||||
const a=.55*(ease(t/.2)-ease((t-.7)/.2)),pour=a>.45,[sx,sy]=rot(190,108,a)
|
||||
for(const[x0,ph]of[[184,0],[222,.5]])for(const[w,s]of[[13,'#111'],[6,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();for(let y=176;y>=128;y-=2)c.lineTo(x0+(2+4*(176-y)/48)*sin((176-y)/36*T-t*T*2+ph*T),y);c.stroke()}
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.ellipse(204,234,46,9,0,0,T);c.fill();c.stroke()
|
||||
for(const[w,s]of[[25,'#111'],[11,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(236,204,12,-PI/2,PI/2),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.moveTo(170,186);c.lineTo(176,222);c.quadraticCurveTo(178,230,188,230);c.lineTo(220,230);c.quadraticCurveTo(230,230,232,222);c.lineTo(238,186);c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(204,186,34,8,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(204,187,27,5,0,0,T);c.fill();c.fillStyle='#fff'
|
||||
if(pour){c.strokeStyle='#fff';c.lineWidth=2.5;const r=(t*6)%1;c.beginPath();c.ellipse(204,187,6+18*r,1.5+3*r,0,0,T);c.stroke();c.strokeStyle='#111'}
|
||||
if(pour)for(const[w,s]of[[14,'#111'],[6,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(sx,sy),c.quadraticCurveTo(sx+8,sy+18+2*sin(8*T*t),204,186),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.save();c.translate(...P);c.rotate(a);c.translate(-P[0],-P[1])
|
||||
for(const[w,s]of[[27,'#111'],[13,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(50,140,22,PI*.5,PI*1.5),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.moveTo(136,140);c.quadraticCurveTo(164,138,176,112);c.lineTo(192,104);c.lineTo(186,120);c.quadraticCurveTo(170,164,136,172);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(72,180,56,12,5);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(50,150);c.bezierCurveTo(50,104,76,92,100,92);c.bezierCurveTo(124,92,148,104,148,150);c.quadraticCurveTo(148,186,112,186);c.lineTo(88,186);c.quadraticCurveTo(50,186,50,150);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(70,98);c.quadraticCurveTo(100,64,130,98);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.arc(100,72,9,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5
|
||||
if(pour)for(const x of[84,116])c.beginPath(),c.arc(x,140,8,PI*1.15,PI*1.85),c.stroke()
|
||||
else{c.fillStyle='#111';for(const x of[84,116])c.beginPath(),c.ellipse(x,138,5.5,7.5,0,0,T),c.fill();c.fillStyle='#fff';for(const x of[82,114])c.beginPath(),c.arc(x,135,2.2,0,T),c.fill()}
|
||||
c.beginPath();c.arc(100,150,10,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=3;for(const x of[66,134])for(const o of[-5,0,5])c.beginPath(),c.moveTo(x+o-2,164),c.lineTo(x+o+2,156),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// toaster pops two slices of toast that hop up and drop back in, the lever snapping up then pushed down again
|
||||
const{sin,PI,min,max}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
const ease=u=>(u=min(1,max(0,u)),u<.5?2*u*u:1-2*(1-u)**2)
|
||||
const toast=(c,x,y,a)=>{
|
||||
c.save();c.translate(x,y);c.rotate(a)
|
||||
c.beginPath();c.moveTo(-22,60);c.lineTo(-22,6);c.bezierCurveTo(-36,-2,-28,-26,0,-24);c.bezierCurveTo(28,-26,36,-2,22,6);c.lineTo(22,60);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(-13,60);c.lineTo(-13,8);c.bezierCurveTo(-24,0,-18,-14,0,-14);c.bezierCurveTo(18,-14,24,0,13,8);c.lineTo(13,60);c.stroke()
|
||||
c.restore();c.lineWidth=7
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const hop=(t0,H,s)=>{const u=(t-t0)/.42;return u>0&&u<1?[H*4*u*(1-u),s*sin(PI*u)]:[0,0]}
|
||||
const[ha,ra]=hop(.3,76,-.3),[hb,rb]=hop(.35,62,.25)
|
||||
const ly=196-56*ease((t-.3)/.04)+56*ease((t-.8)/.15),j=t<.3?1.5*sin(12*T*t)*sin(PI*t/.3):0,up=t>=.3&&t<.55
|
||||
c.translate(128,236);c.scale(1.14,1.14);c.translate(-128,-236)
|
||||
toast(c,104,122-ha,ra);toast(c,152,122-hb,rb)
|
||||
if(t>=.3&&t<.42)for(const d of[-1,1])for(const[w,s]of[[11,'#111'],[4,'#fff']]){c.lineWidth=w;c.strokeStyle=s;for(const[a,r0]of[[-.5,0],[0,6],[.5,0]]){const x=128+d*(96+r0),y=82;c.beginPath();c.moveTo(x+d*12*sin(a+.9),y-12*sin(a+1.2));c.lineTo(x+d*30*sin(a+.9),y-30*sin(a+1.2));c.stroke()}}
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.save();c.translate(j,0)
|
||||
for(const x of[66,162])c.beginPath(),c.roundRect(x,214,28,14,5),c.fill(),c.stroke()
|
||||
c.beginPath();c.roundRect(200,ly-7,26,14,6);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(48,116,160,104,24);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(70,134);c.lineTo(186,134);c.stroke();c.lineWidth=7
|
||||
c.fillStyle='#111'
|
||||
if(up)for(const x of[104,152])c.beginPath(),c.arc(x,162,10,0,T),c.fill()
|
||||
else for(const x of[104,152])c.beginPath(),c.ellipse(x,164,6,8,0,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[101,149])c.beginPath(),c.arc(x+(up?-1:0),up?158:160,up?3.5:2.5,0,T),c.fill()
|
||||
c.lineWidth=5
|
||||
if(up){c.beginPath();c.ellipse(128,188,7,9,0,0,T);c.fillStyle='#111';c.fill()}
|
||||
else{c.beginPath();c.arc(128,176,12,.15*PI,.85*PI);c.stroke()}
|
||||
c.lineWidth=3;for(const x of[80,176])for(const o of[-6,0,6])c.beginPath(),c.moveTo(x+o-2,186),c.lineTo(x+o+3,178),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
// tornado of stacked swirl bands twisting and swaying, marks sliding round each band, debris whirling and dust puffing at the base
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t)=>{
|
||||
const N=8,B=[...Array(N)].map((_,k)=>{const f=k/(N-1);return[128+(4+30*f*f)*sin(t*T-2.6*f),40+k*24,10+92*(1-f)**1.3,16-6*f]})
|
||||
const deb=[[2.5,0,0],[4.2,2.1,1],[5.6,4.2,0]].map(([k,o,ty])=>{const b=B[Math.round(k)],a=2*T*t+o,r=b[2]+20;return[b[0]+r*cos(a),40+k*24+r*.22*sin(a),sin(a),ty,a]})
|
||||
const piece=([x,y,_,ty,a])=>{c.lineWidth=4;c.save();c.translate(x,y);c.rotate(a*1.5);c.beginPath();ty?c.rect(-9,-4,18,8):c.arc(0,0,5,0,T);c.fill();c.stroke();c.restore()}
|
||||
for(const d of deb)if(d[2]<0)piece(d)
|
||||
for(const[dx,r,o]of[[-22,10,0],[20,9,2],[0,9,4]])c.lineWidth=7,c.beginPath(),c.arc(B[N-1][0]+dx,226,r+2*sin(2*T*t+o),0,T),c.fill(),c.stroke()
|
||||
B.forEach(([x,y,r,h],k)=>{
|
||||
c.lineWidth=7;c.beginPath();c.ellipse(x,y,r,h,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const j of[0,1]){const a=((2*T*t+j*PI+k*1.3)%T+T)%T;if(a>.4&&a<PI-.4)c.beginPath(),c.ellipse(x,y,r-7,h-5,0,a-.4,a+.4),c.stroke()}
|
||||
})
|
||||
c.lineWidth=7;for(const d of deb)if(d[2]>=0)piece(d)
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// paper ball tossed in an arc into a happy trash bin, the lid flips open to catch it and the bin bounces
|
||||
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 lid=.65*(ease((t-.18)/.14)-ease((t-.56)/.12)),land=t>.56&&t<.8?(t-.56)/.24:0,sq=land?.08*sin(land*PI*2)*(1-land):0
|
||||
const bp=(t-.06)/.48
|
||||
c.save();c.translate(158,232);c.scale(1+sq,1-sq);c.translate(-158,-232)
|
||||
c.save();c.translate(228,110);c.rotate(lid)
|
||||
c.beginPath();c.roundRect(-144,-12,148,18,8);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(-88,-26,32,16,7);c.fill();c.stroke()
|
||||
c.restore()
|
||||
c.restore()
|
||||
if(bp<1){
|
||||
const s=min(1,t/.06),q=min(1,max(0,bp)),x=(1-q)**2*50+2*(1-q)*q*88+q*q*158,y=(1-q)**2*184+2*(1-q)*q*-30+q*q*130
|
||||
c.save();c.translate(x,y);c.rotate(q*5);c.scale(s,s)
|
||||
c.beginPath();c.arc(0,0,24,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(-15,-7);c.lineTo(-3,-2);c.lineTo(5,-15);c.moveTo(-10,12);c.lineTo(3,5);c.lineTo(15,10);c.moveTo(12,-10);c.lineTo(7,3);c.stroke()
|
||||
c.restore();c.lineWidth=7
|
||||
}
|
||||
c.save();c.translate(158,232);c.scale(1+sq,1-sq);c.translate(-158,-232)
|
||||
c.beginPath();c.moveTo(90,118);c.lineTo(226,118);c.lineTo(212,232);c.lineTo(104,232);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=5;for(const x of[124,158,192])c.beginPath(),c.moveTo(x,136),c.lineTo(x+(x-158)*.08,168),c.stroke()
|
||||
const hap=t>.56&&t<.92
|
||||
c.fillStyle='#111';c.lineWidth=6
|
||||
for(const d of[-1,1]){c.beginPath();if(hap)c.arc(158+d*26,198,9,1.15*PI,1.85*PI),c.stroke();else c.arc(158+d*26,196,7,0,T),c.fill()}
|
||||
c.beginPath();c.arc(158,206,10,.15*PI,.85*PI);c.stroke()
|
||||
c.restore();c.fillStyle='#fff'
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// trumpet tooting three times, a valve pressing on each note, the bell flaring and sound waves rolling out
|
||||
const{sin,PI,floor}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
export default(c,t)=>{
|
||||
const p=(3*t)%1,n=floor(3*t),toot=sin(PI*p)
|
||||
for(const o of[0,.5]){
|
||||
const q=(t+o)%1,s=.4*sin(PI*q),x=206+20*q+6*sin(q*T*2),y=88-66*q
|
||||
if(s<.08)continue
|
||||
c.save();c.translate(x,y);c.scale(s,s)
|
||||
D(c,()=>{c.moveTo(18,-6);c.lineTo(18,-80);c.quadraticCurveTo(26,-56,44,-50)},16,6)
|
||||
c.lineWidth=7/s;c.beginPath();c.ellipse(0,0,22,15,-.35,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
for(const r of[14+30*p,2+30*p])if(r>12)D(c,()=>c.arc(214,128,r,-.6,.6))
|
||||
c.translate(6,4)
|
||||
D(c,()=>{c.moveTo(140,124);c.bezierCurveTo(160,124,160,164,140,164);c.lineTo(66,164);c.bezierCurveTo(50,164,50,140,66,140)},22,10)
|
||||
D(c,()=>{c.moveTo(26,124);c.lineTo(150,124)},22,10)
|
||||
c.beginPath();c.moveTo(12,112);c.quadraticCurveTo(20,124,12,136);c.lineTo(28,128);c.lineTo(28,120);c.closePath();c.fill();c.stroke()
|
||||
for(let k=0;k<3;k++){
|
||||
const x=80+24*k,d=k==n?8*toot:0
|
||||
D(c,()=>{c.moveTo(x,100);c.lineTo(x,86+d)},10,4)
|
||||
c.beginPath();c.ellipse(x,84+d,11,5,0,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(x-7,104,14,66,5);c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(x-10,98,20,10,4);c.fill();c.stroke()
|
||||
}
|
||||
c.save();c.translate(146,124);c.scale(1+.06*toot,1+.1*toot)
|
||||
c.beginPath();c.moveTo(-2,-8);c.bezierCurveTo(24,-9,38,-22,50,-34);c.lineTo(50,34);c.bezierCurveTo(38,22,24,9,-2,8);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(50,0,8,34,0,0,T);c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// retro tv with wobbling rabbit-ear antennas and snowy static flickering on the screen
|
||||
// the static cycles through three fixed noise patterns so the file stays small
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=12,delay=80
|
||||
let s=7;const rnd=()=>(s=s*16807%2147483647)/2147483647
|
||||
const noise=[0,1,2].map(()=>Array.from({length:22*17},()=>rnd()<.5))
|
||||
export default(c,t,i)=>{
|
||||
for(const[d,a0,L]of[[-1,-2.1,70],[1,-1.05,80]]){
|
||||
const a=a0+.1*sin(t*T*2+d)
|
||||
for(const[w,s2]of[[13,'#111'],[5,'#fff']])c.lineWidth=w,c.strokeStyle=s2,c.beginPath(),c.moveTo(128,86),c.lineTo(128+cos(a)*L,86+sin(a)*L),c.stroke()
|
||||
c.lineWidth=6;c.strokeStyle='#111';c.beginPath();c.arc(128+cos(a)*L,86+sin(a)*L,8,0,T);c.fill();c.stroke()
|
||||
}
|
||||
c.lineWidth=7;c.beginPath();c.ellipse(128,90,26,12,0,PI,0);c.fill();c.stroke()
|
||||
for(const x of[72,184])for(const[w,s2]of[[22,'#111'],[8,'#fff']])c.lineWidth=w,c.strokeStyle=s2,c.beginPath(),c.moveTo(x,210),c.lineTo(x+(x<128?-8:8),232),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.beginPath();c.roundRect(32,88,192,124,20);c.fill();c.stroke()
|
||||
const scr=()=>{c.beginPath();c.roundRect(48,104,132,92,16)}
|
||||
c.save();scr();c.clip();const n=noise[i%3]
|
||||
c.fillStyle='#111';for(let y=0;y<17;y++)for(let x=0;x<22;x++)if(n[y*22+x])c.fillRect(48+x*6,104+y*6,6,6)
|
||||
c.restore();c.fillStyle='#fff';scr();c.stroke()
|
||||
for(const y of[124,156])c.beginPath(),c.arc(202,y,10,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=4;for(const y of[180,190])c.beginPath(),c.moveTo(194,y),c.lineTo(210,y),c.stroke()
|
||||
c.lineWidth=5;for(const[y,a]of[[124,.6+t*T],[156,-.4]])c.beginPath(),c.moveTo(202,y),c.lineTo(202+cos(a)*8,y+sin(a)*8),c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// puffy-cheeked wind cloud blowing, its cheeks swelling as dashed gusts stream out to the right
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
export default(c,t)=>{
|
||||
const pf=1+.08*(1-cos(2*T*t))/2,G=[
|
||||
()=>{c.moveTo(156,112);c.bezierCurveTo(184,92,204,110,224,94);c.arc(224,108,14,-PI/2,PI*.9)},
|
||||
()=>{c.moveTo(162,128);c.bezierCurveTo(190,120,210,142,240,130)},
|
||||
()=>{c.moveTo(156,144);c.bezierCurveTo(180,166,196,152,214,176);c.arc(202,184,14,-.6,PI*1.3)}]
|
||||
c.setLineDash([34,22]);c.lineDashOffset=-2*t*56
|
||||
for(const g of G)for(const[w,s]of[[11,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),g(),c.stroke()
|
||||
c.setLineDash([]);c.strokeStyle='#111'
|
||||
const P=[[62,108,36],[102,82,40],[92,148,34],[50,154,26],[132,108,30],[140,138,22*pf]]
|
||||
c.lineWidth=14;for(const[x,y,r]of P)c.beginPath(),c.arc(x,y,r,0,T),c.stroke()
|
||||
for(const[x,y,r]of P)c.beginPath(),c.arc(x,y,r,0,T),c.fill()
|
||||
c.lineWidth=5;for(const[x,d]of[[84,1],[116,-1]])c.beginPath(),c.moveTo(x-8*d,100),c.lineTo(x+4*d,107),c.lineTo(x-8*d,114),c.stroke()
|
||||
c.lineWidth=4;for(const x of[78,110])c.beginPath(),c.arc(x,96,12,1.2*PI,1.7*PI),c.stroke()
|
||||
c.beginPath();c.arc(132,134,14*pf,-.2*PI,.6*PI);c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.ellipse(158,126,9,11,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(159,126,4,6,0,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// yo-yo drops down its string spinning, hangs there a beat, then climbs back up to the finger
|
||||
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
const D=(c,f,a=11,b=4)=>{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'}
|
||||
export default(c,t)=>{
|
||||
const y=114+82*(1-cos(t*T))/2,a=3*T*t
|
||||
D(c,()=>{c.moveTo(128,62);c.lineTo(128,y)},9,3)
|
||||
if(abs(sin(t*T))>.3)for(const s of[0,PI])D(c,()=>c.arc(128,y,58,a+s,a+s+.8))
|
||||
c.beginPath();c.arc(128,y,44,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128,y,32,0,T);c.stroke()
|
||||
for(let k=0;k<3;k++){const b=a+k*T/3;c.beginPath();c.moveTo(128+cos(b)*9,y+sin(b)*9);c.quadraticCurveTo(128+cos(b+.8)*24,y+sin(b+.8)*24,128+cos(b+.4)*31,y+sin(b+.4)*31);c.stroke()}
|
||||
c.fillStyle='#111';c.beginPath();c.arc(128,y,8,0,T);c.fill()
|
||||
c.lineWidth=7;c.fillStyle='#fff'
|
||||
c.beginPath();c.roundRect(112,-30,32,98,16);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.roundRect(119,40,18,20,7);c.stroke()
|
||||
c.beginPath();for(const y of[12,19])c.moveTo(119,y),c.quadraticCurveTo(128,y+4,137,y);c.stroke()
|
||||
c.lineWidth=5;c.beginPath();c.ellipse(128,58,19,6,0,0,T);c.stroke()
|
||||
}
|
||||
Reference in New Issue
Block a user