Bring the minimalist section to 50 with 46 new creatures, 500 total

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-23 14:52:04 +00:00
co-authored by Claude Opus 5.5
parent f25e39b727
commit 11965fb704
138 changed files with 1295 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
// arctic fox curled up asleep in its tail: it breathes slowly, twitches an ear, peeks with one eye and little z's float up
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const b=sin(T*t),tw=t>.3&&t<.36?.35:0,pk=t>.6&&t<.7
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=3.5
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
for(const i of[0,1]){const q=(t+i/2)%1,s=sin(PI*q);c.save();c.translate(108+30*q,88-56*q);c.scale(s,s)
c.beginPath();c.moveTo(-7,-7);c.lineTo(7,-7);c.lineTo(-7,7);c.lineTo(7,7);c.stroke();c.restore()}
c.lineWidth=6
c.translate(136,210);c.scale(1+.015*b,1+.03*b);c.translate(-136,-210)
shape(()=>c.ellipse(140,158,80,52,0,0,T))
for(const[x,y,r]of[[64,110,-.4],[94,104,.15+tw]]){c.save();c.translate(x,y);c.rotate(r)
shape(()=>{c.moveTo(-13,8);c.quadraticCurveTo(-5,-26,0,-28);c.quadraticCurveTo(5,-26,13,8)});c.restore()}
shape(()=>c.ellipse(82,134,34,28,.25,0,T))
shape(()=>c.ellipse(54,150,18,12,.4,0,T))
shape(()=>{c.moveTo(206,166);c.bezierCurveTo(216,214,120,228,62,202);c.bezierCurveTo(36,192,32,166,48,160);c.bezierCurveTo(70,172,130,190,192,158)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5
c.beginPath();c.moveTo(48,156);c.bezierCurveTo(70,168,130,186,192,154);c.stroke()
c.beginPath();c.ellipse(82,134,37,31,.25,-.7,1.2);c.stroke()
if(pk)c.beginPath(),c.arc(70,132,5,0,T),c.fill()
else c.beginPath(),c.arc(70,130,6,.15*PI,.85*PI),c.stroke()
c.beginPath();c.arc(41,147,4.5,0,T);c.fill()
c.beginPath();c.arc(172,156,30,-.8*PI,-.15*PI);c.stroke()
}
+24
View File
@@ -0,0 +1,24 @@
// bao bun cat: a soft steamed bun with cat ears and a pleated top, it squishes, blinks and puffs curls of steam
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const q=sin(T*t*2),bl=t>.7&&t<.76
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(128,128);c.scale(1.12,1.12);c.translate(-128,-128)
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
for(const[i,x]of[104,128,152].entries()){
const L=30+10*sin(T*t+i*2.1),y0=78
c.lineWidth=5;c.beginPath()
for(let y=0;y<=L;y+=2)c.lineTo(x+6*sin(y/9-T*t*2+i),y0-y)
c.stroke()
}
c.lineWidth=6
c.translate(128,214);c.scale(1+.035*q,1-.045*q);c.translate(-128,-214)
for(const d of[-1,1])shape(()=>{c.moveTo(128+d*30,104);c.lineTo(128+d*58,66);c.lineTo(128+d*76,124)})
shape(()=>{c.moveTo(52,212);c.bezierCurveTo(36,140,84,98,128,98);c.bezierCurveTo(172,98,220,140,204,212);c.quadraticCurveTo(128,222,52,212)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3
c.beginPath();for(let a=0;a<2.6*PI;a+=.2){const r=a*4.2;c.lineTo(128+r*cos(-a),122+.42*r*sin(-a))}c.stroke()
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*26,160,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*26,162,6.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(122,172,6,.1*PI,.9*PI);c.arc(134,172,6,.1*PI,.9*PI);c.stroke()
}
+33
View File
@@ -0,0 +1,33 @@
// beaver gnawing a stick like corn on the cob: the stick slides side to side, its cheeks puff, wood chips spit out and it blinks
const{sin,cos,PI,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const s=12*sin(T*t),j=2.5*max(0,sin(T*t*6)),bl=t>.7&&t<.76
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
const tail=()=>c.ellipse(190,206,46,19,-.45+.06*sin(T*t*2),0,T)
c.lineWidth=5;c.beginPath();c.moveTo(58+s,136);c.quadraticCurveTo(44+s,118,50+s,102);c.stroke();c.lineWidth=6
c.save();c.translate(50+s,102);c.rotate(-.5+.15*sin(T*t*2));shape(()=>{c.moveTo(0,0);c.quadraticCurveTo(14,-10,4,-28);c.quadraticCurveTo(-10,-12,0,0)});c.restore()
shape(tail);c.save();c.translate(190,206);c.rotate(-.45+.06*sin(T*t*2));c.strokeStyle='#111';c.lineWidth=2.5
c.beginPath();c.moveTo(4,-12);c.lineTo(16,12);c.moveTo(22,-12);c.lineTo(34,10);c.moveTo(6,12);c.lineTo(30,-12);c.stroke();c.restore()
shape(()=>c.ellipse(128,172,52,52,0,0,T))
for(const d of[-1,1])shape(()=>c.ellipse(128+d*26,224,17,9,0,0,T))
for(const d of[-1,1])shape(()=>c.arc(128+d*36,62,11,0,T))
for(const d of[-1,1])shape(()=>c.arc(128+d*24,112,22+j*.6,0,T))
shape(()=>c.ellipse(128,92,44,40,0,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*20,84,5.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*20,86,5.5,0,T),c.fill()
c.beginPath();c.ellipse(128,104,9,6,0,0,T);c.fill()
c.fillStyle='#fff';c.lineWidth=3;c.beginPath();c.rect(119,114+j,18,15);c.fill();c.stroke()
c.beginPath();c.moveTo(128,114+j);c.lineTo(128,129+j);c.stroke()
c.strokeStyle='#fff';c.lineWidth=6;c.beginPath();c.roundRect(52+s,132,152,20,10);c.fill();c.stroke()
// the stick's dark edge only shows over the body, outside it the rim already outlines it
c.save();c.beginPath();c.ellipse(128,172,52,52,0,0,T);for(const d of[-1,1])c.moveTo(128+d*24+22,112),c.arc(128+d*24,112,22,0,T);c.clip()
c.strokeStyle='#111';c.lineWidth=3.5;c.beginPath();c.roundRect(52+s,132,152,20,10);c.stroke();c.restore();c.strokeStyle='#111'
c.lineWidth=2.5;for(const x of[70,104,150,174])c.beginPath(),c.moveTo(x+s,138),c.lineTo(x+10+s,138),c.moveTo(x+6+s,146),c.lineTo(x+14+s,146),c.stroke()
c.lineWidth=3.5;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*38+s,142,10,13,0,0,T),c.fill(),c.stroke()
for(let i=0;i<3;i++){const q=(t*2+i/3)%1,d=i%2?1:-1
c.save();c.translate(128+d*(16+70*q),128-60*q+90*q*q);c.rotate(T*q*d);c.beginPath();c.ellipse(0,0,9*(1-q*.3),5.5*(1-q*.3),0,0,T);c.fill();c.stroke();c.restore()}
}
+36
View File
@@ -0,0 +1,36 @@
// cheshire cat: it vanishes bit by bit, tail first, then body, then head, until only the grin floats there, then it comes back
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
const ss=x=>x<0?0:x>1?1:x*x*(3-2*x),k=(t,a,b,c,d)=>t<.5?1-ss((t-a)/(b-a)):ss((t-c)/(d-c))
export default(c,t)=>{
const tl=k(t,.06,.18,.86,.96),bd=k(t,.16,.3,.74,.88),hd=k(t,.28,.42,.6,.76),bl=t>.04&&t<.08
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()},at=(x,y,z,f)=>{c.save();c.translate(x,y);c.scale(z,z);c.translate(-x,-y);f();c.restore()}
c.translate(128,128);c.scale(.94,.94);c.translate(-128,-124+4*sin(T*t))
if(tl>0){c.lineWidth=16;c.setLineDash([150*tl,400]);c.beginPath();c.moveTo(170,206);c.quadraticCurveTo(150,226,90,220);c.quadraticCurveTo(60,218,52,200+5*sin(T*t*2));c.stroke();c.setLineDash([])
c.fillStyle=c.strokeStyle='#111';c.lineWidth=4;for(const[i,x]of[138,108,78].entries())if(tl>.2+i*.25)c.beginPath(),c.moveTo(x,211+(x-108)*.03),c.lineTo(x+4,225),c.stroke()}
if(bd>0)at(128,104,bd,()=>{
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
shape(()=>{c.moveTo(128,104);c.bezierCurveTo(186,104,192,222,128,222);c.bezierCurveTo(64,222,70,104,128,104)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=4
for(const d of[-1,1])for(const y of[140,162])c.beginPath(),c.moveTo(128+d*41,y),c.quadraticCurveTo(128+d*35,y+4,128+d*31,y+10),c.stroke()
for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*22,214),c.lineTo(128+d*22,222),c.stroke()
})
if(tl>.9&&bd>.99){c.strokeStyle='#111';c.lineWidth=3.5;c.beginPath();c.moveTo(96,206);c.quadraticCurveTo(130,212,168,204);c.stroke()}
if(hd>0)at(128,108,hd,()=>{
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
for(const d of[-1,1])shape(()=>{c.moveTo(128+d*24,48);c.lineTo(128+d*44,12);c.lineTo(128+d*50,60)})
shape(()=>c.ellipse(128,80,52,42,0,0,T))
c.fillStyle=c.strokeStyle='#111';c.lineWidth=4
for(const x of[112,128,144])c.beginPath(),c.moveTo(x,40+(x==128?-2:2)),c.lineTo(x,54+(x==128?2:0)),c.stroke()
for(const d of[-1,1])for(const y of[70,82])c.beginPath(),c.moveTo(128+d*50,y),c.lineTo(128+d*38,y+3),c.stroke()
c.lineWidth=3.5;for(const d of[-1,1])if(bl)c.beginPath(),c.arc(128+d*20,70,7,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.ellipse(128+d*20,72,7,9,0,0,T),c.fill()
c.beginPath();c.moveTo(122,86);c.lineTo(134,86);c.lineTo(128,92);c.closePath();c.fill()
})
const y=(x,k)=>96+k*2*((x-84)/88)*(1-(x-84)/88)
c.fillStyle='#fff';c.strokeStyle='#111';c.lineWidth=3.5
c.beginPath();c.moveTo(84,96);c.quadraticCurveTo(128,112,172,96);c.quadraticCurveTo(128,154,84,96);c.fill();c.stroke()
c.lineWidth=2;c.beginPath();c.moveTo(88,99);c.quadraticCurveTo(128,130,168,99);c.stroke()
for(let x=96;x<170;x+=12)c.beginPath(),c.moveTo(x,y(x,16)+1),c.lineTo(x,y(x,58)-1),c.stroke()
}
+26
View File
@@ -0,0 +1,26 @@
// chochin-obake, a paper lantern yokai swinging from its hook: its one big eye glances around and blinks, its long tongue licks out and wags
const{sin,cos,PI,sqrt,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const bl=t>.44&&t<.5,lk=sin(T*t*2),gx=6*sin(T*t+1)
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(128,14);c.rotate(.12*sin(T*t));c.scale(1.06,1.06);c.translate(-128,-10)
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
c.lineWidth=4;c.beginPath();c.moveTo(128,12);c.lineTo(128,46);c.stroke()
c.beginPath();c.arc(128,16,7,0,T);c.stroke();c.lineWidth=6
for(const y of[50,198])shape(()=>c.roundRect(96,y,64,14,4))
shape(()=>c.ellipse(128,130,62,70,0,0,T))
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3
for(const y of[50,198])c.beginPath(),c.moveTo(100,y+(y<99?14:0)),c.lineTo(156,y+(y<99?14:0)),c.stroke()
for(let y=76;y<=190;y+=19){const w=62*sqrt(max(0,1-((y-130)/70)**2))-6;c.beginPath();c.moveTo(128-w,y);c.quadraticCurveTo(128,y+5,128+w,y);c.stroke()}
c.fillStyle=c.strokeStyle='#fff';c.beginPath();c.ellipse(128,104,24,21,0,0,T);c.fill()
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5
if(bl)c.beginPath(),c.arc(128,100,20,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.ellipse(128,104,24,21,0,0,T),c.stroke(),c.beginPath(),c.arc(128+gx,106,9,0,T),c.fill()
c.beginPath();c.moveTo(92,148);c.quadraticCurveTo(128,158,164,146);c.quadraticCurveTo(130,196,92,148);c.fill()
const tx=150+30*lk,ty=200-6*lk
const tg=()=>{c.beginPath();c.moveTo(128,164);c.quadraticCurveTo(132+12*lk,206,tx,ty);c.stroke()}
c.save();c.beginPath();c.ellipse(128,130,62,70,0,0,T);c.rect(96,198,64,14);c.clip();c.lineWidth=23;tg();c.restore()
c.strokeStyle='#fff';c.lineWidth=16;tg()
c.strokeStyle='#111';c.lineWidth=3;c.beginPath();c.moveTo(130,172);c.quadraticCurveTo(132+10*lk,198,(tx+128)/2+8*lk,(ty+170)/2+6);c.stroke()
}
+26
View File
@@ -0,0 +1,26 @@
// cockatoo on a perch: it bobs side to side, flicks its crest up into a fan and lays it back down, and blinks
const{sin,PI,min}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const q=t>.1&&t<.6?sin(PI*(t-.1)/.5):0,g=min(1,q*1.5),s=sin(T*t*2),bl=t>.78&&t<.84
c.fillStyle=c.strokeStyle='#fff'
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.lineWidth=14;c.beginPath();c.moveTo(50,214);c.lineTo(206,214);c.stroke()
c.translate(124,214);c.rotate(.07*s);c.translate(-124,-214)
c.lineWidth=6
shape(()=>{c.moveTo(100,190);c.lineTo(94,238);c.lineTo(116,236);c.lineTo(124,194)})
for(let i=0;i<5;i++){
const a=-PI*.97+i*.05+g*(PI*.22+i*.3),L=32+i*3
c.save();c.translate(132,76);c.rotate(a);shape(()=>{c.moveTo(0,-6);c.bezierCurveTo(L*.5,-9,L*.9,-6,L,5);c.quadraticCurveTo(L*.5,4,0,6)});c.restore()
}
shape(()=>c.ellipse(122,162,40,54,-.25,0,T))
shape(()=>c.arc(146,98,34,0,T))
c.fillStyle=c.strokeStyle='#111'
// beak gets a white ring so it still shows on a black page
const bk=()=>{c.moveTo(170,86);c.quadraticCurveTo(198,88,194,120);c.quadraticCurveTo(186,108,172,110);c.ellipse(176,114,9,7,0,0,T)}
c.lineWidth=7;c.strokeStyle='#fff';c.beginPath();bk();c.stroke();c.strokeStyle='#111';c.beginPath();bk();c.fill()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(154,92,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(154,94,6,0,T),c.fill()
c.lineWidth=3.5;c.beginPath();c.moveTo(146,134);c.quadraticCurveTo(152,180,108,204);c.stroke()
for(const x of[112,134])c.beginPath(),c.arc(x,208,5,PI*.9,PI*2.1),c.stroke()
}
+31
View File
@@ -0,0 +1,31 @@
// cricket: lifts its wings and buzzes them together to chirp, little music notes float off, antennae sway and it blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
const note=(c,x,y,z)=>{c.save();c.translate(x,y);c.scale(z,z);c.beginPath();c.ellipse(0,0,8,6,-.4,0,T);c.fill();c.stroke()
c.beginPath();c.moveTo(7,-2);c.lineTo(7,-28);c.quadraticCurveTo(14,-20,20,-18);c.stroke();c.restore()}
export default(c,t)=>{
const w=.42+.1*sin(T*t*8),bl=t>.7&&t<.77,a=.06*sin(T*t)
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.lineWidth=4
for(const[i,x]of[0,1,2].entries()){const q=(t+i/3)%1;note(c,96-30*q+6*sin(T*q),104-74*q,sin(PI*q))}
c.lineWidth=3
for(const[k,[x,y]]of[[224,42],[236,68]].entries())c.beginPath(),c.moveTo(184,112),c.bezierCurveTo(184,70,x-34,y-24+4*sin(T*t+k),x+4*sin(T*t+k),y+4*cos(T*t+k)),c.stroke()
c.lineWidth=5
for(const[x0,x1]of[[164,176],[140,138],[120,104]])c.beginPath(),c.moveTo(x0,160),c.lineTo(x1,186),c.lineTo(x1+(x1>130?8:-6),206),c.stroke()
c.lineWidth=6
c.save();c.translate(150,130);c.rotate(-w)
shape(()=>{c.moveTo(0,0);c.quadraticCurveTo(-50,-14,-96,-4);c.quadraticCurveTo(-50,12,0,10)});c.restore()
shape(()=>c.ellipse(110,150,52,22,.05,0,T))
shape(()=>c.arc(180,134,26,0,T))
c.save();c.translate(150,130);c.rotate(-w*.6)
shape(()=>{c.moveTo(0,0);c.quadraticCurveTo(-50,-14,-96,-4);c.quadraticCurveTo(-50,12,0,10)})
c.strokeStyle='#111';c.lineWidth=2.5;c.beginPath();c.moveTo(-8,4);c.quadraticCurveTo(-50,0,-86,-2);c.stroke();c.restore()
c.lineWidth=5;c.beginPath();c.moveTo(70,136);c.lineTo(58,204);c.lineTo(44,206);c.stroke()
c.strokeStyle='#111';c.lineWidth=3;c.fillStyle='#fff'
c.save();c.translate(96,154);c.rotate(-.55);c.beginPath();c.ellipse(0,0,36,13,0,0,T);c.fill();c.stroke();c.restore()
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(186,126,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(186,128,6.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(196,142,6,.2*PI,.8*PI);c.stroke()
}
+26
View File
@@ -0,0 +1,26 @@
// dodo waddling in place: its round body rocks side to side as its big feet step, its head bobs, the tail tuft wobbles and it blinks
const{sin,cos,PI,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const r=.07*sin(T*t*2),hb=4*sin(T*t*4),bl=t>.62&&t<.68,L=p=>8*max(0,sin(T*t*2+p))
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(-8,0)
for(const[x,p]of[[104,0],[140,PI]]){const l=L(p)
c.lineWidth=13;c.beginPath();c.moveTo(x,186);c.lineTo(x+2,220-l);c.stroke()
c.lineWidth=6;for(const a of[-.25,0,.25])c.beginPath(),c.moveTo(x+2,222-l),c.lineTo(x+2+20*cos(a),222-l+8*sin(a)+2),c.stroke()}
c.translate(122,222);c.rotate(r);c.translate(-122,-222)
for(const[x,y,q]of[[58,104,0],[46,120,1],[56,90,2]]){c.save();c.translate(x,y);c.rotate(.15*sin(T*t*2-q));shape(()=>c.arc(0,0,11,0,T));c.restore()}
shape(()=>c.ellipse(118,142,60,54,0,0,T))
c.lineWidth=30;c.beginPath();c.moveTo(146,120);c.lineTo(164,88+hb);c.stroke()
c.translate(0,hb)
c.lineWidth=6;shape(()=>c.arc(170,78,28,0,T))
shape(()=>{c.moveTo(184,62);c.quadraticCurveTo(222,58,236,80);c.quadraticCurveTo(242,98,228,100);c.quadraticCurveTo(226,90,214,92);c.quadraticCurveTo(196,96,184,94);c.closePath()})
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(170,70,5.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(170,72,5.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(190,82);c.quadraticCurveTo(208,82,226,90);c.stroke()
c.beginPath();c.moveTo(196,68);c.quadraticCurveTo(204,64,212,68);c.stroke()
c.translate(0,-hb)
c.lineWidth=3.5;c.beginPath();c.moveTo(96,124);c.quadraticCurveTo(122,120,132,142);c.quadraticCurveTo(116,160,100,150);c.stroke()
}
+32
View File
@@ -0,0 +1,32 @@
// dormouse asleep in a teacup: its back rises and falls with each breath, z's drift up, an ear twitches, its tail hangs over the side
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const b=sin(T*t),tw=t>.55&&t<.62?.3:0
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
for(let i=0;i<2;i++){
const q=(t+i/2)%1,z=sin(PI*q)*(7+5*q),x=150+44*q+6*sin(T*q),y=84-58*q
c.lineWidth=4;c.beginPath();c.moveTo(x-z,y-z);c.lineTo(x+z,y-z);c.lineTo(x-z,y+z);c.lineTo(x+z,y+z);c.stroke()
}
c.lineWidth=6
shape(()=>c.ellipse(128,216,98,16,0,0,T))
c.lineWidth=12;c.beginPath();c.ellipse(56,166,18,22,0,0,T);c.stroke()
c.lineWidth=15;c.beginPath();c.moveTo(170,136);c.quadraticCurveTo(214,130,216+4*sin(T*t+1),194);c.stroke();c.lineWidth=6
shape(()=>c.ellipse(128,140,70,14,0,0,T))
shape(()=>c.ellipse(142,140-3*b,50,24+4*b,0,0,T))
c.save();c.translate(82,102+b);c.rotate(-tw);shape(()=>c.arc(0,0,15,0,T));c.restore()
shape(()=>c.arc(122,100+b,15,0,T))
shape(()=>c.ellipse(102,126+b,30,25,0,0,T))
shape(()=>{c.moveTo(58,140);c.bezierCurveTo(60,196,94,212,128,212);c.bezierCurveTo(162,212,196,196,198,140);c.ellipse(128,140,70,14,0,0,PI)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5
c.beginPath();c.ellipse(128,140,70,14,0,.04*PI,.96*PI);c.stroke()
c.beginPath();c.ellipse(128,210,40,6,0,.05*PI,.95*PI);c.stroke()
c.beginPath();c.ellipse(102,126+b,30,25,0,-1.3,-.1);c.stroke()
c.lineWidth=3;c.beginPath();c.arc(82,104+b,7,-2.6,-.6);c.stroke();c.beginPath();c.arc(122,102+b,7,-2.6,-.6);c.stroke()
c.beginPath();c.moveTo(128,184);c.bezierCurveTo(112,170,108,186,128,196);c.bezierCurveTo(148,186,144,170,128,184);c.fill()
for(const d of[-1,1])c.beginPath(),c.arc(102+d*12,122+b,5,.15*PI,.85*PI),c.stroke()
c.beginPath();c.arc(102,134+b,3.5,0,T);c.fill()
c.strokeStyle='#111';c.fillStyle='#fff';c.lineWidth=3
for(const x of[72,134])c.beginPath(),c.ellipse(x,152,10,7,0,0,T),c.fill(),c.stroke()
}
+24
View File
@@ -0,0 +1,24 @@
// dove cooing with an olive sprig: it puffs out its round chest, bobs its little head, lifts its slender tail and blinks
const{sin,cos,PI,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const b=sin(T*t*2),p=max(0,sin(T*t)),bl=t>.62&&t<.68,hx=184+7*b,hy=82+3*max(0,b)
c.fillStyle=c.strokeStyle='#fff';c.translate(4,-8)
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.lineWidth=6;for(const x of[122,144])c.beginPath(),c.moveTo(x,176),c.lineTo(x-2,204),c.moveTo(x-9,206),c.lineTo(x+5,206),c.stroke()
c.save();c.translate(84,150);c.rotate(-.08-.14*p);shape(()=>{c.moveTo(0,-14);c.quadraticCurveTo(-34,-12,-68,0);c.quadraticCurveTo(-34,12,0,16)});c.restore()
shape(()=>c.ellipse(120,150,56,32,-.08,0,T))
shape(()=>c.ellipse(156+4*p,138-2*p,38+8*p,40+6*p,0,0,T))
c.lineWidth=24;c.beginPath();c.moveTo(166,112);c.lineTo(hx-3,hy+6);c.stroke();c.lineWidth=6
shape(()=>c.arc(hx,hy,16,0,T))
shape(()=>{c.moveTo(hx+13,hy-3);c.lineTo(hx+24,hy+2);c.lineTo(hx+13,hy+6)})
// olive sprig hanging from the beak, it swings a little behind the head bob
c.save();c.translate(hx+20,hy+3);c.rotate(.15*sin(T*t*2-1))
c.lineWidth=3.5;c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(14,10,12,30);c.stroke()
c.lineWidth=4;for(const[x,y,r]of[[7,6,-.5],[13,16,.9],[13,30,1.6]])shape(()=>c.ellipse(x+5*cos(r),y+5*sin(r),8,3.5,r,0,T))
c.restore()
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(hx+4,hy-4,4.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(hx+4,hy-2,4.5,0,T),c.fill()
c.lineWidth=3.5;c.beginPath();c.moveTo(72,150);c.bezierCurveTo(98,122,146,110,156,132);c.bezierCurveTo(162,152,118,166,72,150);c.stroke()
}
+20
View File
@@ -0,0 +1,20 @@
// dumbo octopus paddling: it flaps its ear fins, its webbed skirt puffs open and shut, it bobs and blinks
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const w=sin(T*t*2),p=sin(T*t*2-1.2),bl=t>.4&&t<.46
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(0,-7*sin(T*t*2-2))
for(const d of[-1,1]){c.save();c.translate(128+d*44,96);c.scale(d,1);c.rotate(-.45*w);shape(()=>c.ellipse(24,-6,28,15,-.3,0,T));c.restore()}
const W=52+10*p,Y=198-6*p,X=[0,1,2,3,4,5].map(k=>128-W+k*W*2/5),Yk=X.map(x=>Y-14*((x-128)/W)**2)
shape(()=>{c.moveTo(82,128);c.quadraticCurveTo(70,170,X[0],Yk[0])
for(let k=1;k<6;k++)c.quadraticCurveTo((X[k-1]+X[k])/2,Y-22,X[k],Yk[k])
c.quadraticCurveTo(186,170,174,128)})
shape(()=>c.ellipse(128,110,52,50,0,0,T))
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3
for(const k of[1,2,3,4])c.beginPath(),c.moveTo(128+(X[k]-128)*.5,160),c.lineTo(X[k],Yk[k]-8),c.stroke()
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*20,120,6.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*20,122,6.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(128,134,6,.2*PI,.8*PI);c.stroke()
}
+32
View File
@@ -0,0 +1,32 @@
// ermine in its winter coat: it pokes up out of a snow hole, sniffs, glances back over its shoulder, blinks, dips down for a moment and pops back up
const{sin,PI,min,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
const sm=x=>(x=min(1,max(0,x)))*x*(3-2*x)
export default(c,t)=>{
const u=(t+.5)%1-.5,up=1-sm((u+.16)/.08)+sm((u+.04)/.08),bl=t>.26&&t<.3||t>.7&&t<.74
const hd=t>.36&&t<.6?-1:1,hr=.12*sin(T*t*3),pw=sm((up-.7)/.3)
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
const mound=()=>{c.moveTo(24,224);c.bezierCurveTo(32,180,88,166,128,166);c.bezierCurveTo(168,166,224,180,232,224);c.closePath()}
const seen=()=>{c.beginPath();c.rect(0,0,256,174);c.ellipse(128,174,38,11,0,0,T);c.clip()}
const at=(h,f)=>{c.save();c.translate(128,174+172*(1-up));if(h)c.translate(0,-96),c.rotate(hr*hd),c.scale(hd,1);f();c.restore()}
const parts=[[0,()=>{c.moveTo(-26,60);c.lineTo(-26,-40);c.bezierCurveTo(-26,-74,-18,-90,-6,-98);c.lineTo(14,-90);c.bezierCurveTo(16,-70,28,-50,26,-20);c.lineTo(26,60)}],
[1,()=>c.arc(-2,-27,7,0,T)],[1,()=>c.arc(-14,-24,9,0,T)],[1,()=>c.ellipse(2,-8,24,19,0,0,T)],[1,()=>c.ellipse(28,-2,18,11,.15,0,T)]]
shape(mound)
c.fillStyle='#111';c.beginPath();c.ellipse(128,174,38,11,0,0,T);c.fill();c.fillStyle='#fff'
// a dark edge wherever the white ermine overlaps the white snow, so it doesn't melt into it
c.save();c.beginPath();mound();c.clip();seen();c.strokeStyle='#111';c.lineWidth=12
for(const[h,f]of parts)at(h,()=>{c.beginPath();f();c.stroke()})
c.restore()
c.save();seen()
for(const[h,f]of parts)at(h,()=>shape(f))
at(1,()=>{c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(12,-14,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(12,-12,5,0,T),c.fill()
c.beginPath();c.ellipse(44,-4+1.5*sin(T*t*6),5,4,.2,0,T);c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(41,4);c.quadraticCurveTo(34,9,26,6);c.stroke()})
c.restore()
if(pw)for(const x of[110,146]){c.save();c.translate(x,183);c.scale(pw,pw)
c.strokeStyle='#111';c.lineWidth=12;c.beginPath();c.ellipse(0,0,10,6,0,0,T);c.stroke()
c.strokeStyle='#fff';c.lineWidth=6;shape(()=>c.ellipse(0,0,10,6,0,0,T));c.restore()}
}
+33
View File
@@ -0,0 +1,33 @@
// leopard gecko: it grins, flicks its tongue up to lick its own eyeball shut, curls its chubby tail and blinks
const{sin,cos,PI,max,atan2,hypot}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
const bz=(p,q,r,s)=>[(1-s)**2*p[0]+2*(1-s)*s*q[0]+s*s*r[0],(1-s)**2*p[1]+2*(1-s)*s*q[1]+s*s*r[1]]
export default(c,t)=>{
const q=t>.3&&t<.62?sin(PI*(t-.3)/.32):0,tw=sin(T*t),bl=t>.82&&t<.88||q>.55
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(121,132);c.scale(1.08,1.08);c.translate(-124,-144)
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
// tail: a tapered tube along a curve, fat at the hip
const A=[78,138],B=[30,140+6*tw],C=[40,184],L=[],R=[]
for(let i=0;i<=16;i++){const s=i/16,[x,y]=bz(A,B,C,s),[x2,y2]=bz(A,B,C,s+.01),a=atan2(y2-y,x2-x),w=18*(1-s)+5;L.push([x-w*sin(a),y+w*cos(a)]);R.unshift([x+w*sin(a),y-w*cos(a)])}
shape(()=>{for(const[x,y]of[...L,...R])c.lineTo(x,y);c.closePath()})
shape(()=>c.arc(...bz(A,B,C,1),5,0,T))
c.lineWidth=11
for(const[x,y,dx]of[[166,148,16],[92,152,-16]]){c.beginPath();c.moveTo(x,y);c.lineTo(x+dx,y+28);c.stroke()}
c.lineWidth=6
for(const[x,dx]of[[182,1],[76,-1]])for(const a of[-.6,0,.6])shape(()=>c.arc(x+dx*8*cos(a+PI/2)+8*sin(a),182+8*cos(a)-2,4.5,0,T))
shape(()=>c.ellipse(124,138,56,26,-.05,0,T))
shape(()=>c.ellipse(184,118,36,27,-.2,0,T))
if(q>0){
const P=[214,128],Q=[246,88],E=[190,96],pts=[...Array(13)].map((_,i)=>bz(P,Q,E,q*i/12))
c.strokeStyle='#111';c.lineWidth=17;c.beginPath();for(const p of pts)c.lineTo(...p);c.stroke()
c.beginPath();c.arc(...pts[12],9.5,0,T);c.fillStyle='#111';c.fill()
c.strokeStyle=c.fillStyle='#fff';c.lineWidth=10;c.beginPath();for(const p of pts)c.lineTo(...p);c.stroke()
c.beginPath();c.arc(...pts[12],6.5,0,T);c.fill()
}
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(186,102,9,.15*PI,.85*PI),c.stroke()
else{c.beginPath();c.arc(186,106,10,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(189,102,3,0,T);c.fill();c.fillStyle='#111'}
c.lineWidth=3.5;c.beginPath();c.moveTo(214,126);c.quadraticCurveTo(196,138,172,128);c.stroke()
for(const[x,y]of[[100,126],[122,122],[144,128],[112,142],[136,144],[62,140]])c.beginPath(),c.arc(x,y,3.5,0,T),c.fill()
}
+23
View File
@@ -0,0 +1,23 @@
// ghost cat floating: a cat head on a sheet-like body that trails off into a curling tail, it bobs, dangles its droopy paws, the hem ripples and it blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const s=sin(T*t),bl=t>.3&&t<.36,w=x=>5*sin(x/12-T*t*2)
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(115,124+9*s);c.rotate(.05*cos(T*t));c.translate(-128,-124)
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
for(const d of[-1,1])shape(()=>{c.moveTo(128+d*16,74);c.lineTo(128+d*42,38);c.lineTo(128+d*54,84)})
shape(()=>{
c.moveTo(78,100);c.bezierCurveTo(74,58,182,58,178,100)
c.bezierCurveTo(182,140,176,160,196,176+w(10));c.bezierCurveTo(216,190+w(20),236,170,222,152+6*sin(T*t*2+1))
c.bezierCurveTo(240,166,236,210,196,212);c.lineTo(180,212)
for(let x=180;x>82;x-=16)c.quadraticCurveTo(x-8,226+w(x),x-16,212+w(x-16)*.4)
c.bezierCurveTo(76,180,82,136,78,100)})
c.lineWidth=13
for(const d of[-1,1]){const k=6*sin(T*t*2+d)
c.beginPath();c.moveTo(128+d*44,132);c.quadraticCurveTo(128+d*66,118+k*.4,128+d*76,130+k);c.stroke()}
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*20,92,6.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*20,95,6.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(122,108,6,.1*PI,.9*PI);c.arc(134,108,6,.1*PI,.9*PI);c.stroke()
}
+32
View File
@@ -0,0 +1,32 @@
// goat bleating: it throws its head back with a wide open mouth and sound marks, its tail flicks and it blinks
const{sin,cos,PI,max,min}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const h=t>.3&&t<.7?sin(PI*(t-.3)/.4):0,wg=.4*sin(T*t*3),bl=t>.82&&t<.88
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(-20,8)
c.save();c.translate(60,118);c.rotate(wg);shape(()=>{c.moveTo(-6,4);c.quadraticCurveTo(-14,-14,-4,-24);c.quadraticCurveTo(4,-8,8,2)});c.restore()
c.lineWidth=12
for(const[x,y,e]of[[78,150,76],[96,152,98],[146,150,144],[164,148,168]])c.beginPath(),c.moveTo(x,y),c.lineTo(e,204),c.stroke()
c.lineWidth=6;shape(()=>c.ellipse(116,138,60,32,0,0,T))
c.lineWidth=26;c.beginPath();c.moveTo(158,128);c.lineTo(180,98);c.stroke()
c.save();c.translate(178,102);c.rotate(-.4*h);c.translate(-178,-102)
c.lineWidth=10;c.beginPath();c.moveTo(190,72);c.quadraticCurveTo(182,38,152,46);c.stroke()
c.lineWidth=8;c.beginPath();c.moveTo(200,74);c.quadraticCurveTo(196,44,170,42);c.stroke()
c.lineWidth=6
shape(()=>c.ellipse(170,90,17,6,-.25-.3*h,0,T))
shape(()=>c.ellipse(198,94,32,19,.6,0,T))
shape(()=>{c.moveTo(204,108);c.lineTo(222,114);c.lineTo(208,140);c.closePath()})
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(198,84,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(198,86,5,0,T),c.fill()
c.beginPath();c.arc(224,104,3.5,0,T);c.fill()
if(h>.05)c.beginPath(),c.ellipse(218,116,6*h+2,9*h,.6,0,T),c.fill()
else c.lineWidth=3,c.beginPath(),c.moveTo(214,114),c.quadraticCurveTo(219,118,224,114),c.stroke()
if(h>.25){c.strokeStyle='#fff';c.lineWidth=5
for(const r of[18,30])c.beginPath(),c.arc(220,116,r+4*h,-.5,.9),c.stroke()}
c.restore()
c.strokeStyle='#111';c.lineWidth=2.5
for(const e of[76,98,144,168])c.beginPath(),c.moveTo(e,206),c.lineTo(e,210),c.stroke()
}
+26
View File
@@ -0,0 +1,26 @@
// hare sitting sideways: it slowly rocks its rear up and thumps its long hind foot down twice, dust ticks out, its ears twitch, then it blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const u=(t*2)%1,l=u<.34?sin(PI/2*u/.34):u<.4?cos(PI/2*(u-.34)/.06):0,hit=u>=.4&&u<.6,j=hit?1-(u-.4)/.2:0,bl=t>.86&&t<.92
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(122,138);c.scale(.94,.94);c.translate(-128,-128)
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
if(hit){const q=(u-.4)/.2;c.lineWidth=4
for(const[x,d]of[[108,-1],[222,1]])for(const a of[.45,1.05]){const r=10+14*q;c.beginPath();c.moveTo(x+d*r*cos(a),218-r*sin(a));c.lineTo(x+d*(r+10)*cos(a),218-(r+10)*sin(a));c.stroke()}
c.lineWidth=6}
c.translate(100,220);c.rotate(-.15*l);c.translate(-100,-220+2*j)
for(const[x,y,r]of[[124,60,.62],[110,58,.42]]){c.save();c.translate(x,y);c.rotate(r+.05*sin(T*t*2+r*9)-.22*j*(r>.5));shape(()=>c.ellipse(0,0,13,46,0,0,T));c.restore()}
shape(()=>c.ellipse(166,212,46,9,0,0,T))
shape(()=>{c.moveTo(96,140);c.bezierCurveTo(112,106,196,100,214,148);c.bezierCurveTo(226,184,214,206,190,208);c.lineTo(116,208);c.bezierCurveTo(94,206,86,168,96,140)})
shape(()=>c.arc(218,160,13,0,T))
shape(()=>c.roundRect(92,164,17,56,8))
shape(()=>c.ellipse(84,122,36,28,-.18,0,T))
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3
c.beginPath();c.moveTo(109,184);c.lineTo(109,212);c.stroke()
c.beginPath();c.moveTo(184,136);c.bezierCurveTo(200,160,196,190,168,204);c.stroke()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(76,114,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(76,116,6.5,0,T),c.fill()
c.beginPath();c.arc(50,122,4,0,T);c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(50,126);c.quadraticCurveTo(52,134,60,134);c.stroke()
}
+33
View File
@@ -0,0 +1,33 @@
// baby dragon peeking out of its cracked egg: it pops up wearing the top shell like a hat, flaps its little wings, looks left and right, blinks, then sinks back
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
const ez=x=>(x=min(1,max(0,x)),x*x*(3-2*x))
export default(c,t)=>{
const h=ez((t-.06)/.18)-ez((t-.8)/.14),lx=h*sin(T*t*2),bl=t>.5&&t<.56,hx=128+4*lx,hy=124-44*h,fl=h*sin(T*t*4)
const zig=(x0,x1,y,n,k)=>{for(let i=1;i<n;i++)c.lineTo(x0+i*(x1-x0)/n,y+(i%2?-k:k));c.lineTo(x1,y)}
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
for(const d of[-1,1]){
c.save();c.translate(128+d*30,150-30*h);c.rotate(d*(.5+.25*fl));c.scale(d,1)
shape(()=>{c.moveTo(0,0);c.quadraticCurveTo(10,-34,40,-46);c.quadraticCurveTo(36,-30,46,-20);c.quadraticCurveTo(34,-18,38,-6);c.quadraticCurveTo(22,-8,18,4)})
c.restore()
}
shape(()=>{c.moveTo(hx-28,hy+90);c.lineTo(hx-20,hy+10);c.lineTo(hx+20,hy+10);c.lineTo(hx+28,hy+90)})
c.save();c.translate(hx,hy);c.rotate(.06*lx)
c.lineWidth=9;for(const d of[-1,1])c.beginPath(),c.moveTo(d*20,-22),c.quadraticCurveTo(d*26,-40,d*40,-44),c.stroke()
c.lineWidth=6
shape(()=>c.ellipse(0,0,38,33,0,0,T))
c.save();c.translate(-6,-30);c.rotate(-.28+.06*sin(T*t*2))
shape(()=>{c.moveTo(-28,4);c.bezierCurveTo(-28,-30,28,-30,28,4);zig(28,-28,4,6,5)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5;c.beginPath();c.moveTo(28,4);zig(28,-28,4,6,5);c.stroke()
c.restore()
c.fillStyle=c.strokeStyle='#111';const ex=6*lx
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(ex+d*15,-2,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(ex+d*15,0,6.5,0,T),c.fill()
for(const d of[-1,1])c.beginPath(),c.arc(ex*1.3+d*5,14,2.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(ex*1.3,16,8,.25*PI,.75*PI);c.stroke()
c.restore()
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
shape(()=>{c.moveTo(67,140);zig(67,189,140,7,9);c.ellipse(128,162,64,70,0,-.32,PI+.32)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5;c.beginPath();c.moveTo(67,140);zig(67,189,140,7,9);c.stroke()
}
+36
View File
@@ -0,0 +1,36 @@
// jerboa hopping in place: it crouches, springs up on its long kangaroo legs with ears swept back and tufted tail swinging, then lands and squashes
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=75,rim=3,rimColor='#111'
// leg pose e: -1 crouched, 1 fully pushed off. keys are [t,e], eased between
const K=[[0,-1],[.2,1],[.5,.2],[.78,.5],[.92,-1],[1,-1]]
const pose=t=>{let i=0;while(K[i+1][0]<t)i++;const[a,x]=K[i],[b,y]=K[i+1],u=(t-a)/(b-a);return x+(y-x)*(1-cos(PI*u))/2}
const L=[22,34,26],G=232
const ang=e=>{const l=(a,b,c)=>e<0?b+(b-a)*e:b+(c-b)*e;return[l(.7,1,1.7),l(2.7,2.3,1.6),l(.2,.4,1.4)]}
const leg=e=>{let x=0,y=0;const p=[[0,0]];for(const[k,a]of ang(e).entries())x+=L[k]*cos(a),y+=L[k]*sin(a),p.push([x,y]);return p}
const rest=t=>{const p=leg(pose(t)).at(-1);return[142-p[0],G-14-p[1]]}
export default(c,t)=>{
const air=t>.2&&t<.78,p=(t-.2)/.58,e=pose(t)
let[bx,by]=rest(t)
if(air){const[x0,y0]=rest(.2),[x1,y1]=rest(.78);bx=x0+(x1-x0)*p;by=y0+(y1-y0)*p-130*p*(1-p)}
const ear=-.3*cos(T*(t-.2)),tl=.4*sin(T*(t-.15)),bl=t>.42&&t<.5
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.save();c.translate(bx-26,by+8);c.rotate(tl)
c.lineWidth=5;c.beginPath();c.moveTo(0,0);c.bezierCurveTo(-24,10,-48,6,-66,-8);c.stroke()
c.lineWidth=6;shape(()=>c.ellipse(-72,-12,13,8,.5,0,T));c.restore()
for(const d of[0,6]){
const P=leg(e).map(([x,y])=>[bx-14+x-d,by+14+y])
c.lineWidth=7;c.beginPath();c.moveTo(...P[0]);for(const q of P.slice(1))c.lineTo(...q);c.stroke()
}
shape(()=>c.ellipse(bx-12,by+8,18,22,-.3,0,T))
shape(()=>c.ellipse(bx,by,32,26,-.25,0,T))
const hx=bx+30,hy=by-22
for(const[d,w]of[[-8,0],[2,.25]]){c.save();c.translate(hx+d,hy-14);c.rotate(-.25+ear+w);shape(()=>c.ellipse(0,-22,11,24,0,0,T));c.restore()}
shape(()=>c.ellipse(hx,hy,24,20,.2,0,T))
c.lineWidth=5;c.beginPath();c.moveTo(bx+22,by+6);c.lineTo(bx+32,by+18);c.stroke()
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(hx+6,hy-4,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(hx+6,hy-2,6,0,T),c.fill()
c.beginPath();c.arc(hx+19,hy,3,0,T);c.fill()
c.lineWidth=2;c.beginPath();c.moveTo(hx+4,hy+10);c.lineTo(hx+17,hy+9);c.moveTo(hx+4,hy+14);c.lineTo(hx+15,hy+17);c.stroke()
}
+24
View File
@@ -0,0 +1,24 @@
// manatee drifting: a chubby sea cow bobbing and tilting, its round tail paddle flexes, a flipper paddles, bubbles rise and it blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const s=sin(T*t),f=sin(T*t*2),bl=t>.54&&t<.6
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
for(const i of[0,1,2]){const q=(t+i/3)%1;shape(()=>c.arc(226+6*sin(T*q*2),100-70*q,3+4*q,0,T))}
c.translate(128,128+8*s);c.rotate(.05*cos(T*t));c.scale(.92,.92);c.translate(-128,-128)
const ty=120-14*sin(T*t-1.4)
c.lineWidth=30;c.beginPath();c.moveTo(96,134);c.quadraticCurveTo(66,132,46,ty);c.stroke()
c.lineWidth=6;shape(()=>c.ellipse(34,ty-2,20,26,.2-.15*sin(T*t-1.4),0,T))
shape(()=>c.ellipse(124,134,74,46,0,0,T))
shape(()=>c.arc(186,120,36,0,T))
shape(()=>c.ellipse(214,134,20,24,-.2,0,T))
c.save();c.translate(168,166);c.rotate(.5+.4*f);shape(()=>c.ellipse(0,18,10,22,0,0,T));c.restore()
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(190,108,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(190,110,5,0,T),c.fill()
for(const[x,y]of[[214,118],[226,124]])c.beginPath(),c.ellipse(x,y,2.5,4,.4,0,T),c.fill()
for(const[x,y]of[[206,136],[216,140],[224,134],[212,146],[222,148]])c.beginPath(),c.arc(x,y,2,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(204,154);c.quadraticCurveTo(212,160,222,156);c.stroke()
c.beginPath();c.arc(186,122,46,.74*PI,1.1*PI);c.stroke()
}
+30
View File
@@ -0,0 +1,30 @@
// marmot standing on its hind legs: it tips its head back and screams with its mouth wide open, shaking all over, then blinks
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const q=t>.28&&t<.82?sin(PI*(t-.28)/.54):0,o=min(1,q*1.7),sh=o>.4?3*sin(T*t*12):0,bl=t>.1&&t<.16
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(128+sh,128);c.scale(1.04,1.04);c.translate(-128,-128)
shape(()=>c.ellipse(182,208,24,11,-.6,0,T))
for(const x of[100,156])shape(()=>c.ellipse(x,226,21,9,0,0,T))
shape(()=>{c.moveTo(128,100);c.bezierCurveTo(194,100,202,228,128,228);c.bezierCurveTo(54,228,62,100,128,100)})
c.save();c.translate(0,-8*o)
for(const d of[-1,1])shape(()=>c.arc(128+d*34,54,13,0,T))
shape(()=>c.ellipse(128,86,46,38,0,0,T))
if(o>.3){c.lineWidth=4;for(const a of[-2.55,-2.15,-1,-.6])c.beginPath(),c.moveTo(128+62*cos(a),86+56*sin(a)),c.lineTo(128+(62+14*o)*cos(a),86+(56+14*o)*sin(a)),c.stroke()}
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5
for(const d of[-1,1])if(o>.3)c.beginPath(),c.moveTo(128+d*25,71),c.lineTo(128+d*14,77),c.lineTo(128+d*25,83),c.stroke()
else if(bl)c.beginPath(),c.arc(128+d*18,76,5.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*18,78,5.5,0,T),c.fill()
c.beginPath();c.ellipse(128,90,6.5,4.5,0,0,T);c.fill()
const my=97,mh=3+20*o
c.lineWidth=3
if(o>.05)c.beginPath(),c.ellipse(128,my+mh,5+9*o,mh,0,0,T),c.fill()
else c.beginPath(),c.moveTo(128,94),c.lineTo(128,98),c.quadraticCurveTo(123,103,117,100),c.moveTo(128,98),c.quadraticCurveTo(133,103,139,100),c.stroke()
c.fillStyle='#fff';c.lineWidth=2.5;c.beginPath();c.rect(122,my+(o>.05?1:2),12,9);c.fill();c.stroke()
c.beginPath();c.moveTo(128,my+1);c.lineTo(128,my+10);c.stroke()
c.restore()
c.strokeStyle='#111';c.fillStyle='#fff';c.lineWidth=3
for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*14,152-4*o,10,13,-d*.3,0,T),c.fill(),c.stroke()
}
+35
View File
@@ -0,0 +1,35 @@
// meerkat on sentry duty: standing tall on its mound with paws held up, it snaps its pointed snout left, front, right, stretches up and blinks
const{sin,cos,PI,min,max,abs,floor,atan2}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
const K=[0,0,-1,-1,0,0,1,1]
export default(c,t)=>{
const n=K.length,u=t*n,i=floor(u),f=min(1,(u-i)/.4),e=f*f*(3-2*f),h=K[i]+(K[(i+1)%n]-K[i])*e,a=abs(h),ph=h*PI/2
const up=5*max(0,sin(T*t*2)),bl=t>.5&&t<.56
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
shape(()=>{c.moveTo(46,238);c.quadraticCurveTo(128,200,210,238);c.closePath()})
c.lineWidth=9;c.beginPath();c.moveTo(146,194);c.quadraticCurveTo(178,190,186,210);c.stroke()
c.lineWidth=6;c.beginPath();c.moveTo(186,210);c.quadraticCurveTo(190,220,200,228);c.stroke()
for(const x of[114,142])shape(()=>c.ellipse(x,222,12,6,0,0,T))
shape(()=>{c.moveTo(117,112-up);c.bezierCurveTo(104,134-up,100,172,106,198);c.quadraticCurveTo(110,218,128,218);c.quadraticCurveTo(146,218,150,198);c.bezierCurveTo(156,172,152,134-up,139,112-up);c.closePath()})
c.translate(0,-up)
const X=128+5*h,Y=82,tx=X+44*h,ty=Y+28-20*a,d=atan2(ty-Y,tx-X),nx=-sin(d),ny=cos(d),mx=(X+tx)/2,my=(Y+ty)/2
c.lineWidth=24;c.beginPath();c.moveTo(128,118);c.lineTo(X,Y+8);c.stroke();c.lineWidth=6
// ears and eyes sit at an angle around the head, so turning the head slides them round and hides the far ones
const E=[-1,1].map(s=>[X+19*sin(s*PI/2+ph*.75),cos(s*PI/2+ph*.75)])
for(const[x,z]of E)if(z>-.3)shape(()=>c.arc(x,Y-4,6.5,0,T))
shape(()=>c.arc(X,Y,19,0,T))
shape(()=>{c.moveTo(X+nx*15,Y+ny*15);c.quadraticCurveTo(mx+nx*8,my+ny*8,tx,ty);c.quadraticCurveTo(mx-nx*8,my-ny*8,X-nx*15,Y-ny*15)})
c.fillStyle=c.strokeStyle='#111'
for(const[x,z]of E)if(z>-.3)c.beginPath(),c.ellipse(x,Y-4,3,4,0,0,T),c.fill()
for(const s of[-1,1]){const al=s*.5+ph,x=X+17*sin(al),y=Y+4,r=-s*.7*(1-a)+h*.3
if(cos(al)<.1)continue
if(bl)c.lineWidth=4,c.beginPath(),c.arc(x,y-3,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.ellipse(x,y,7,5,r,0,T),c.fill()}
c.beginPath();c.ellipse(tx,ty,4.5,4,0,0,T);c.fill()
c.translate(0,up*.5)
c.lineWidth=3.5
for(const s of[-1,1]){
c.beginPath();c.moveTo(128+s*17,122);c.quadraticCurveTo(128+s*22,142,128+s*12,140);c.stroke()
c.fillStyle='#fff';c.beginPath();c.ellipse(128+s*10,147,5,6.5,0,0,T);c.fill();c.stroke()}
}
+32
View File
@@ -0,0 +1,32 @@
// moon rabbit pounding mochi under a crescent moon: it heaves the mallet up, brings it down, the mochi squishes and its ears flop
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const L=t<.5?.5-.5*cos(PI*t/.5):t<.6?1-((t-.5)/.1)**2:0,q=t>.6&&t<.82?sin(PI*(t-.6)/.22):0,bl=t>.3&&t<.36
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.save();c.translate(42,42);c.rotate(.15*sin(T*t));shape(()=>c.arc(0,0,22,0,T))
c.globalCompositeOperation='destination-out';c.beginPath();c.arc(14,-9,21,0,T);c.fill();c.restore()
shape(()=>{c.moveTo(42,166);c.lineTo(102,166);c.bezierCurveTo(110,182,106,206,98,218);c.lineTo(46,218);c.bezierCurveTo(38,206,34,182,42,166)})
shape(()=>c.ellipse(72,166,24+7*q,13-6*q,0,0,T))
c.save();c.translate(170,220);c.rotate(-.06*L+.04*q);c.translate(-170,-220)
const P=[140,140],a=3.3+1.1*L,H=[P[0]+66*cos(a),P[1]+66*sin(a)]
shape(()=>c.ellipse(168,214,26,9,0,0,T))
shape(()=>c.ellipse(174,178,30,38,0,0,T))
shape(()=>c.arc(204,192,11,0,T))
for(const[x,y,r]of[[164,100,.12],[178,104,.5]]){c.save();c.translate(x,y);c.rotate(r+.3*q-.1*L);shape(()=>c.ellipse(0,-26,9,28,0,0,T));c.restore()}
shape(()=>c.ellipse(158,118,28,25,0,0,T))
c.lineWidth=11;c.beginPath();c.moveTo(166,150);c.lineTo(...P);c.lineTo(...H);c.stroke();c.lineWidth=6
shape(()=>c.arc(...P,8,0,T))
c.save();c.translate(...H);c.rotate(a);shape(()=>c.roundRect(-11,-20,22,40,5));c.restore()
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(146,112,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(146,114,5,0,T),c.fill()
c.beginPath();c.arc(133,120,3,0,T);c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(133,122);c.quadraticCurveTo(135,130,142,129);c.stroke()
c.save();c.translate(164,100);c.rotate(.12+.3*q-.1*L);c.beginPath();c.moveTo(0,-12);c.lineTo(0,-42);c.stroke();c.restore()
c.restore()
c.lineWidth=3;c.beginPath();c.moveTo(46,168);c.lineTo(98,168);c.stroke()
if(q>0){c.strokeStyle='#fff';c.lineWidth=4
for(const[x,y,u,v]of[[34,150,-12,-6],[32,164,-14,2],[110,150,12,-6]])c.beginPath(),c.moveTo(x,y),c.lineTo(x+u*q,y+v*q),c.stroke()}
}
+31
View File
@@ -0,0 +1,31 @@
// pika: a round little rock rabbit sits tight, then rears up with ears perked and mouth wide, sound lines popping out as it squeaks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const q=t>.35&&t<.75?sin(PI*(t-.35)/.4):0,bl=t>.12&&t<.18
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(128,222);c.scale(1.1-.05*q,1.1+.08*q);c.translate(-128,-222)
for(const x of[106,150])shape(()=>c.ellipse(x,214,16,8,0,0,T))
shape(()=>c.ellipse(128,170,60,46,0,0,T))
const hy=120-8*q
for(const d of[-1,1])shape(()=>c.arc(128+d*(36+4*q),hy-34-4*q,18,0,T))
shape(()=>c.ellipse(128,hy,48,40,0,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1])c.lineWidth=3,c.beginPath(),c.arc(128+d*(36+4*q),hy-34-4*q,9,PI+.3,-.3),c.stroke()
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*18,hy-6,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*18,hy-4,5.5,0,T),c.fill()
c.beginPath();c.ellipse(128,hy+7,4,3,0,0,T);c.fill()
c.lineWidth=3
if(q>.15)c.beginPath(),c.ellipse(128,hy+18,4+3*q,7*q,0,0,T),c.fill()
else c.beginPath(),c.moveTo(128,hy+9),c.quadraticCurveTo(124,hy+16,119,hy+14),c.moveTo(128,hy+9),c.quadraticCurveTo(132,hy+16,137,hy+14),c.stroke()
for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*24,hy+10),c.lineTo(128+d*40,hy+8),c.moveTo(128+d*24,hy+15),c.lineTo(128+d*38,hy+18),c.stroke()
c.lineWidth=3;for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*14,206),c.quadraticCurveTo(128+d*12,196,128+d*6,192),c.stroke()
if(q>.05){
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
for(const d of[-1,1])for(const a of[-.5,0,.5]){
const r0=62+10*q,r1=r0+16*q,A=(d<0?PI:0)-d*a
c.beginPath();c.moveTo(128+r0*cos(A),hy+r0*sin(A)*.8);c.lineTo(128+r1*cos(A),hy+r1*sin(A)*.8);c.stroke()
}
}
}
+39
View File
@@ -0,0 +1,39 @@
// pillbug: trundles along on its little legs, curls up into a striped ball with an eye peeking from the seam, rolls forward and back, then unrolls and blinks
const{sin,cos,PI,min,max,sqrt}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
const N=7,Lb=170,W=40,G=204,ez=u=>(1-cos(PI*min(1,max(0,u))))/2,rot=([x,y],a)=>[x*cos(a)-y*sin(a),x*sin(a)+y*cos(a)]
export default(c,t)=>{
const q=t<.5?ez((t-.14)/.16):ez((.86-t)/.16),r=t>.3&&t<.7?.65*sin(T*(t-.3)/.4):0,bl=t>.9&&t<.96
const th=2.5+(T-2.5)*q,R=Lb/th,z=1+.25*q,lg=10*(1-q),yb=-R*cos(th/2)+W/2,m=q*q*(3-2*q)
const a0=-PI/2-th/2,a1=-PI/2+th/2,P=(a,k=R)=>[k*cos(a),k*sin(a)],s=1-q,o=R+W/2
c.fillStyle=c.strokeStyle='#fff'
c.translate(116+12*q+z*o*r*q,G-z*(yb+lg));c.scale(z,z);c.rotate(r*q-q)
if(lg>1){c.lineWidth=5;for(const[i,x]of[-44,-16,12,40].entries()){const k=4*sin(T*t*4+i*PI/2);c.beginPath();c.moveTo(x,yb-8);c.lineTo(x+k,yb+lg);c.stroke()}}
if(s>.05){
c.save();c.translate(...P(a0-6/R));c.rotate(a0-PI/2);c.scale(s,s);c.lineWidth=5
for(const d of[-1,1])c.beginPath(),c.moveTo(0,d*6),c.lineTo(16,d*11),c.stroke();c.restore()
c.save();c.translate(...P(a1+16/R));c.rotate(a1+PI/2);c.scale(s,s)
c.lineWidth=3.5;for(const d of[0,1])c.beginPath(),c.moveTo(10,2),c.quadraticCurveTo(24+6*d,-6+4*sin(T*t*2+d),36+4*d,8+10*d),c.stroke()
c.lineWidth=6;c.beginPath();c.arc(0,0,19,0,T);c.fill();c.stroke()
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(4,-8,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(4,-6,5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(10,3,5,.1*PI,.7*PI);c.stroke()
c.restore()
}
if(q>.85){
const p=(q-.85)/.15;c.lineWidth=3.5
for(const[a,b]of[[-.16,-.26],[-.04,.02]])c.beginPath(),c.moveTo(...P(PI/2+a,o-4)),c.lineTo(...P(PI/2+b,o-4+14*p)),c.stroke()
}
c.beginPath();c.arc(0,0,R,a0,a1);c.closePath();c.fill();c.lineWidth=W;c.stroke()
// plates: lines across the dome when open, parallel curved bands across the ball when shut, only drawn on top of the body
c.globalCompositeOperation='source-atop';c.strokeStyle=c.fillStyle='#111';c.lineWidth=3
for(let k=1;k<N;k++){
const[tx,ty]=P(a0+k/N*th,o-6),O=[[tx,ty],[tx*.9+5,(ty+yb)/2],[tx*.82,yb-5]]
const u=-1+2*k/N,h=(o-4)*sqrt(1-u*u),x=(o-4)*u,C=[[x,-h],[x+.7*h,0],[x,h]].map(v=>rot(v,1))
const[A,B,D]=O.map((v,j)=>v.map((w,i)=>w+(C[j][i]-w)*m))
c.beginPath();c.moveTo(...A);c.quadraticCurveTo(...B,...D);c.stroke()
}
if(q>.85)c.beginPath(),c.arc(...P(PI/2-.32,o-13),4.5*(q-.85)/.15,0,T),c.fill()
c.globalCompositeOperation='source-over'
}
+24
View File
@@ -0,0 +1,24 @@
// polar bear sniffing the air: it lifts its long snout, nose twitching, little sniff puffs pop out, then lowers its head and blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const h=.5-.5*cos(T*t),sn=h>.6?sin(T*t*8):0,bl=t>.9&&t<.96
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
for(const x of[106,130,180,204])shape(()=>c.roundRect(x-12,160,24,54,11))
shape(()=>c.ellipse(162,148,66,46,0,0,T))
shape(()=>c.arc(228,138,8,0,T))
c.save();c.translate(114,126);c.rotate(.45*h)
shape(()=>c.ellipse(-12,0,30,26,0,0,T))
shape(()=>c.arc(-30,-28,8.5,0,T))
shape(()=>c.ellipse(-44,-7,30,21,.08,0,T))
shape(()=>c.ellipse(-70,1,20,13,.12,0,T))
c.fillStyle=c.strokeStyle='#111'
c.beginPath();c.ellipse(-85,-1+1.5*sn,6,5,0,0,T);c.fill()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(-54,-14,4.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(-54,-12,4.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(-84,9);c.quadraticCurveTo(-78,13,-70,10);c.stroke()
if(sn>0){c.strokeStyle='#fff';c.lineWidth=3.5
for(const r of[16,26])c.beginPath(),c.arc(-88,-1,r,PI-.45*sn,PI+.45*sn),c.stroke()}
c.restore()
}
+31
View File
@@ -0,0 +1,31 @@
// show poodle prancing in place: pompom legs high-step in a trot, its body bobs, ear puffs bounce, the tail pompom wags and it blinks
const{sin,cos,PI,max,abs}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const y=-5*abs(sin(T*t*2)),wg=.3*sin(T*t*2),bl=t>.44&&t<.5
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
const leg=(x,top,l,k)=>{
// thigh swings forward by l, the shin folds back by k, an ankle pompom and a little paw at the end
const a=l,b=l-k,x1=x+32*sin(a),y1=top+32*cos(a),x2=x1+38*sin(b),y2=y1+38*cos(b)
c.lineWidth=9;c.beginPath();c.moveTo(x,top);c.lineTo(x1,y1);c.lineTo(x2,y2);c.stroke()
c.lineWidth=6;shape(()=>c.arc(x1+30*sin(b),y1+30*cos(b),11,0,T));shape(()=>c.ellipse(x2+4,y2,9,5,0,0,T))}
const L=p=>max(0,sin(T*t*2+p))
c.translate(0,y)
leg(152,140,.7*L(PI),1.5*L(PI));leg(92,136,-.2*L(0),-.9*L(0))
c.save();c.translate(70,112);c.rotate(wg);c.lineWidth=7;c.beginPath();c.moveTo(0,0);c.lineTo(-10,-34);c.stroke();c.lineWidth=6;shape(()=>c.arc(-12,-42,14,0,T));c.restore()
c.lineWidth=26;c.beginPath();c.moveTo(86,124);c.lineTo(150,118);c.stroke()
c.lineWidth=6;shape(()=>c.arc(84,126,24,0,T))
c.lineWidth=16;c.beginPath();c.moveTo(160,112);c.lineTo(180,74);c.stroke()
c.lineWidth=6;shape(()=>c.arc(156,118,34,0,T))
leg(166,140,.7*L(0),1.5*L(0));leg(80,138,-.2*L(PI),-.9*L(PI))
shape(()=>c.ellipse(206,80,17,9,.2,0,T))
shape(()=>c.arc(184,72,18,0,T))
shape(()=>c.arc(178,48,19,0,T))
shape(()=>c.ellipse(170,96+2*sin(T*t*2-1),12,19,.1,0,T))
c.fillStyle=c.strokeStyle='#111'
c.beginPath();c.arc(222,78,5,0,T);c.fill()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(192,68,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(192,70,5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(204,88);c.quadraticCurveTo(212,92,220,86);c.stroke()
}
+26
View File
@@ -0,0 +1,26 @@
// possum hanging by its tail from a branch: it swings slowly, its little arms dangle a beat behind, its ear twitches and it blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const a=.13*sin(T*t),b=.3*sin(T*t-1.2),bl=t>.62&&t<.68,tw=t>.3&&t<.38?.35:0
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.lineWidth=14;c.beginPath();c.moveTo(20,32);c.quadraticCurveTo(128,24,236,36);c.stroke()
c.lineWidth=6;shape(()=>c.ellipse(208,24,7,14,.9,0,T));shape(()=>c.ellipse(46,25,7,13,-.8,0,T))
c.translate(128,30);c.rotate(a);c.translate(-128,-30)
c.lineWidth=8;c.beginPath();c.arc(128,30,13,0,T);c.stroke()
c.beginPath();c.moveTo(128,43);c.quadraticCurveTo(118,58,128,76);c.stroke()
c.lineWidth=6
shape(()=>{c.moveTo(128,72);c.bezierCurveTo(104,72,92,100,94,124);c.bezierCurveTo(96,150,112,158,128,158);c.bezierCurveTo(144,158,160,150,162,124);c.bezierCurveTo(164,100,152,72,128,72)})
for(const d of[-1,1]){c.save();c.translate(128+d*26,140);c.rotate(-d*.7+b);c.lineWidth=10;c.beginPath();c.moveTo(0,0);c.lineTo(0,30);c.stroke()
c.lineWidth=6;shape(()=>c.ellipse(0,32,7,8,0,0,T));c.restore()}
c.save();c.translate(98,178);c.rotate(tw);shape(()=>c.arc(0,0,15,0,T))
c.strokeStyle='#111';c.lineWidth=3;c.beginPath();c.arc(2,2,8,.6*PI,1.9*PI);c.stroke();c.restore()
shape(()=>c.arc(124,176,32,0,T))
shape(()=>c.ellipse(150,204,30,15,.95,0,T))
c.fillStyle=c.strokeStyle='#111'
c.beginPath();c.arc(166,228,6,0,T);c.fill()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(138,176,6,1.15*PI,1.85*PI),c.stroke()
else c.beginPath(),c.arc(138,178,6,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(132,206);c.quadraticCurveTo(140,216,150,216);c.stroke()
}
+29
View File
@@ -0,0 +1,29 @@
// potoo on a stump: eyes shut it's just another bit of branch, then the huge eyes pop open, glance left and right, and squeeze shut again
const{sin,PI,min,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const o=t<.3?0:t<.38?(t-.3)/.08:t<.8?1:t<.88?1-(t-.8)/.08:0,lk=t>.42&&t<.78?6*sin(T*(t-.42)/.36):0
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
shape(()=>{c.moveTo(90,240);c.lineTo(96,196);c.lineTo(160,196);c.lineTo(166,240);c.closePath()})
c.strokeStyle='#111';c.lineWidth=3
c.beginPath();c.ellipse(128,196,32,7,0,0,T);c.stroke()
for(const[x,y]of[[106,214],[150,222]])c.beginPath(),c.moveTo(x,y),c.lineTo(x,y+16),c.stroke()
c.strokeStyle='#fff';c.lineWidth=6
c.translate(128,200);c.rotate(.03*sin(T*t));c.scale(1+.04*o,1-.04*o);c.translate(-128,-200)
shape(()=>{c.moveTo(118,196);c.lineTo(128,228);c.lineTo(138,196)})
shape(()=>c.ellipse(128,130,46,74,0,0,T))
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3
for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*42,150),c.quadraticCurveTo(128+d*38,184,128+d*18,198),c.stroke()
for(const d of[-1,1]){
const x=128+d*20,y=100
if(o<.15){c.lineWidth=3.5;c.beginPath();c.moveTo(x-13,y);c.quadraticCurveTo(x,y+4,x+13,y);c.stroke();continue}
c.save();c.translate(x,y);c.scale(1,o)
c.fillStyle='#fff';c.lineWidth=3.5;c.beginPath();c.arc(0,0,15,0,T);c.fill();c.stroke()
c.fillStyle='#111';c.beginPath();c.arc(lk,1,10,0,T);c.fill()
c.fillStyle='#fff';c.beginPath();c.arc(lk+3,-3,3,0,T);c.fill()
c.restore()
}
c.beginPath();c.moveTo(123,114);c.lineTo(133,114);c.lineTo(128,121);c.closePath();c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(104,122);c.quadraticCurveTo(128,130,152,122);c.stroke()
}
+27
View File
@@ -0,0 +1,27 @@
// quail bobbing along: its black topknot nods and springs with every head bob, its little legs step and it blinks
const{sin,cos,PI,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const b=sin(T*t*2),pl=sin(T*t*2-1.3),bl=t>.7&&t<.76,hx=164+6*b,hy=98+5*b
c.fillStyle=c.strokeStyle='#fff';c.translate(6,0)
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.lineWidth=6
for(const k of[0,1]){const x=118+k*14+10*sin(T*t*2+k*PI),y=214-5*max(0,cos(T*t*2+k*PI))
c.beginPath();c.moveTo(118+k*14,186);c.lineTo(x,y);c.moveTo(x-10,y+2);c.lineTo(x+10,y+2);c.stroke()}
c.translate(0,2*b)
shape(()=>{c.moveTo(56,128);c.bezierCurveTo(70,96,150,94,170,124);c.bezierCurveTo(186,170,140,198,108,194);c.bezierCurveTo(72,190,52,160,56,128)})
shape(()=>{c.moveTo(60,124);c.lineTo(34,112);c.lineTo(44,140)})
c.lineWidth=26;c.beginPath();c.moveTo(150,124);c.lineTo(hx-2,hy+6);c.stroke();c.lineWidth=6
shape(()=>c.arc(hx,hy,22,0,T))
c.fillStyle=c.strokeStyle='#111'
c.save();c.translate(hx+4,hy-18);c.rotate(.3*pl)
// white ring so the black plume still shows on a black page
c.beginPath();c.moveTo(-3,0);c.bezierCurveTo(-8,-26,8,-40,24,-34);c.bezierCurveTo(34,-30,30,-16,20,-18);c.bezierCurveTo(12,-20,6,-12,3,0)
c.lineWidth=8;c.strokeStyle='#fff';c.stroke();c.fill();c.restore();c.strokeStyle='#111'
c.beginPath();c.moveTo(hx+18,hy-4);c.quadraticCurveTo(hx+32,hy,hx+19,hy+8);c.fill()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(hx+5,hy-6,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(hx+5,hy-4,5,0,T),c.fill()
c.lineWidth=3.5;c.beginPath();c.moveTo(hx+12,hy+10);c.quadraticCurveTo(hx+2,hy+22,hx-14,hy+18);c.stroke()
c.beginPath();c.moveTo(150,134);c.quadraticCurveTo(128,170,72,146);c.stroke()
for(const[x,y]of[[118,176],[134,166],[100,170]])c.beginPath(),c.arc(x,y,6,PI*.15,PI*.85),c.stroke()
}
+22
View File
@@ -0,0 +1,22 @@
// samoyed grinning: a fluffy white dog with its famous smile pants, tilts its head, perks its ears, wags its plume tail and blinks
const{sin,PI,abs,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const s=sin(T*t),w=sin(T*t*3),pa=sin(T*t*4),bl=t>.44&&t<.5,pk=6*max(0,sin(T*t*2))
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6;c.translate(-22,0)
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.save();c.translate(166,186);c.rotate(.3*w);shape(()=>{c.moveTo(-14,6);c.bezierCurveTo(4,-46,60,-62,68,-24);c.bezierCurveTo(72,-4,44,-2,34,-14);c.bezierCurveTo(28,0,18,14,6,22)});c.restore()
shape(()=>c.ellipse(128,184,48,44,0,0,T))
for(const x of[106,150])shape(()=>c.ellipse(x,222,16,10,0,0,T))
c.translate(128,120);c.rotate(.12*s);c.translate(-128,-120)
for(const d of[-1,1])shape(()=>{c.moveTo(128+d*18,72);c.quadraticCurveTo(128+d*38,22-pk,128+d*48,30-pk);c.quadraticCurveTo(128+d*58,50,128+d*54,82)})
for(const i of[-2,-1,0,1,2])shape(()=>c.arc(128+i*24,132-abs(i)*8,18,0,T))
shape(()=>c.ellipse(128,100,54,46,0,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*22,90,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*22,92,6,0,T),c.fill()
c.beginPath();c.ellipse(128,106,9,6,0,0,T);c.fill()
c.lineWidth=3.5;c.beginPath();c.moveTo(106,116);c.quadraticCurveTo(128,124,150,116);c.quadraticCurveTo(146,140,128,140);c.quadraticCurveTo(110,140,106,116);c.fill()
c.lineWidth=3;c.fillStyle='#fff';c.beginPath();c.ellipse(128,140+3*pa,9,9,0,0,T);c.fill();c.stroke()
c.beginPath();c.moveTo(128,134+3*pa);c.lineTo(128,144+3*pa);c.stroke()
}
+20
View File
@@ -0,0 +1,20 @@
// sea angel swimming: a little clione flaps its wing-feet and bobs on every beat, a tiny heart glowing in its belly
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const w=sin(T*t*2),bl=t>.7&&t<.76
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
for(const[i,x]of[-64,60].entries()){const q=(t+i/2)%1;c.beginPath();c.arc(128+x+4*sin(T*q),214-150*q,5*sin(PI*q),0,T);c.fill()}
c.translate(0,-7*sin(T*t*2+.9))
for(const d of[-1,1]){c.save();c.translate(128+d*16,108);c.scale(d,1);c.rotate(.5*w)
shape(()=>{c.moveTo(0,-6);c.bezierCurveTo(24,-38,62,-42,68,-22);c.bezierCurveTo(72,-4,40,12,0,10)});c.restore()}
shape(()=>{c.moveTo(104,92);c.bezierCurveTo(96,140,112,192,128,222);c.bezierCurveTo(144,192,160,140,152,92)})
for(const d of[-1,1])shape(()=>c.arc(128+d*15,58,8,0,T))
shape(()=>c.arc(128,82,28,0,T))
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3
c.beginPath();c.moveTo(128,166);c.bezierCurveTo(106,150,114,132,128,143);c.bezierCurveTo(142,132,150,150,128,166);c.stroke()
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*11,80,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*11,82,5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(128,92,5,.2*PI,.8*PI);c.stroke()
}
+21
View File
@@ -0,0 +1,21 @@
// sea bunny inching along: a fluffy sea slug wiggles its dark-tipped bunny ears, sways its little gill flower and blinks
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
const D=[[150,136],[178,148],[124,128],[202,166],[162,172],[136,156],[190,130],[112,180],[184,186],[214,146]]
export default(c,t)=>{
const s=sin(T*t*2),bl=t>.5&&t<.56
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(132,202);c.scale(1+.05*s,1-.05*s);c.translate(-132,-202)
c.save();c.translate(200,126);c.rotate(.25*sin(T*t*2+1))
for(let i=-2;i<=2;i++){c.save();c.rotate(i*.4);shape(()=>c.ellipse(0,-16,6,14,0,0,T));c.restore()}
c.restore()
for(const[x,y,r,k]of[[84,124,-.3,0],[112,116,.12,1.6]]){c.save();c.translate(x,y);c.rotate(r+.2*sin(T*t*2+k))
shape(()=>c.ellipse(0,-22,10,25,0,0,T));c.fillStyle='#111';c.beginPath();c.ellipse(0,-34,5.5,9,0,0,T);c.fill();c.restore()}
shape(()=>c.ellipse(132,158,88,46,0,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const[x,y]of D)c.beginPath(),c.arc(x,y,3,0,T),c.fill()
for(const x of[72,96])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(x,148,5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(x,150,5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(84,160,6,.2*PI,.8*PI);c.stroke()
}
+34
View File
@@ -0,0 +1,34 @@
// seagull standing tall: it throws its head back and squawks with its beak wide open, sound lines pop out, then it blinks
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const q=t>.2&&t<.8?sin(PI*(t-.2)/.6):0,o=min(1,q*1.8),bl=t>.86&&t<.92
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(128,128);c.scale(.9,.9);c.translate(-140,-122)
for(const x of[112,136])c.beginPath(),c.moveTo(x,186),c.lineTo(x-2,226),c.stroke(),shape(()=>{c.moveTo(x-17,231);c.lineTo(x+10,231);c.lineTo(x-2,223);c.closePath()})
c.translate(0,-4*q)
shape(()=>{c.moveTo(150,96);c.bezierCurveTo(186,104,194,162,166,184);c.bezierCurveTo(146,200,102,200,82,186)
c.lineTo(40,160);c.lineTo(42,148);c.bezierCurveTo(74,138,110,104,150,96)})
shape(()=>{c.moveTo(90,168);c.lineTo(18,152);c.lineTo(80,146);c.closePath()})
c.save();c.translate(160,100);c.rotate(-.42*q)
shape(()=>c.arc(12,-30,27,0,T))
c.save();c.translate(34,-30);c.rotate(-.1*o)
shape(()=>{c.moveTo(-2,-6);c.quadraticCurveTo(24,-6,40,0);c.quadraticCurveTo(47,3,42,10);c.quadraticCurveTo(38,5,30,6);c.lineTo(0,6)})
c.restore()
c.save();c.translate(34,-24);c.rotate(.6*o)
shape(()=>{c.moveTo(0,0);c.lineTo(36,1);c.quadraticCurveTo(32,6,24,7);c.lineTo(0,6)})
c.fillStyle='#111';c.beginPath();c.arc(26,3,3,0,T);c.fill()
c.restore()
c.lineWidth=4;if(o>.3)for(const a of[-.8,-.3,.2])c.beginPath(),c.moveTo(90+10*cos(a),-26+10*sin(a)),c.lineTo(90+(10+13*o)*cos(a),-26+(10+13*o)*sin(a)),c.stroke()
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5
if(o>.3)c.beginPath(),c.moveTo(10,-42),c.lineTo(21,-36),c.lineTo(10,-31),c.stroke()
else if(bl)c.beginPath(),c.arc(16,-36,5.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(16,-35,5,0,T),c.fill()
c.beginPath();c.moveTo(4,-48);c.lineTo(26,-41);c.stroke()
c.restore()
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5
c.beginPath();c.moveTo(158,118);c.quadraticCurveTo(142,174,90,168);c.stroke()
c.beginPath();c.moveTo(66,149);c.lineTo(18,152);c.lineTo(72,164);c.closePath();c.fill();c.stroke()
c.fillStyle='#fff';for(const x of[34,50])c.beginPath(),c.arc(x,153+(x-34)*.12,2.8,0,T),c.fill()
}
+27
View File
@@ -0,0 +1,27 @@
// shoebill: stands stock-still and deadpan, gives one slow blink, then a stiff little bow of its giant clog bill and straightens back up
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const b=t>.4&&t<.88?sin(PI*(t-.4)/.48)**2:0,bl=t>.14&&t<.26
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=7
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.lineWidth=6;for(const x of[100,128])c.beginPath(),c.moveTo(x+2,186),c.lineTo(x,232),c.moveTo(x-7,234),c.lineTo(x+13,234),c.stroke()
c.translate(118,196);c.rotate(.1*b);c.translate(-118,-196)
c.lineWidth=6
shape(()=>{c.moveTo(92,180);c.lineTo(70,214);c.lineTo(100,200)})
shape(()=>c.ellipse(116,146,40,54,.2,0,T))
c.save();c.translate(136,104);c.rotate(.5*b)
shape(()=>c.ellipse(4,-18,16,24,.15,0,T))
const x=6,y=-40
shape(()=>{c.moveTo(x-18,y-14);c.quadraticCurveTo(x-34,y-20,x-36,y-8);c.quadraticCurveTo(x-28,y-6,x-24,y)})
shape(()=>c.arc(x,y,28,0,T))
shape(()=>{c.moveTo(x+6,y-22);c.bezierCurveTo(x+40,y-26,x+70,y-16,x+84,y-2);c.quadraticCurveTo(x+90,y+8,x+80,y+14)
c.lineTo(x+76,y+6);c.bezierCurveTo(x+60,y+24,x+30,y+28,x+4,y+22);c.closePath()})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3
c.beginPath();c.moveTo(x+14,y+8);c.quadraticCurveTo(x+50,y+14,x+78,y+6);c.stroke()
const ex=x-2,ey=y-6
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(ex,ey-2,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(ex,ey,6,0,PI),c.fill(),c.lineWidth=3.5,c.beginPath(),c.moveTo(ex-8,ey),c.lineTo(ex+8,ey),c.stroke()
c.restore()
c.lineWidth=3;c.beginPath();c.moveTo(144,124);c.quadraticCurveTo(128,170,96,190);c.stroke()
}
+36
View File
@@ -0,0 +1,36 @@
// silk moth fluttering: a fluffy white moth beats its little wings, sways its feathery antennae and blinks its big eyes
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const f=sin(T*t*3),bl=t>.62&&t<.68
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
c.translate(0,4*sin(T*t*3+1.2))
for(const d of[-1,1]){
c.save();c.translate(128+d*12,132);c.scale(d,1);c.rotate(-.24*f-.04)
shape(()=>{c.moveTo(0,8);c.bezierCurveTo(34,6,62,22,56,46);c.bezierCurveTo(42,62,12,52,0,30)})
shape(()=>{c.moveTo(0,-8);c.bezierCurveTo(30,-40,70,-58,94,-52);c.quadraticCurveTo(92,-36,84,-30);c.bezierCurveTo(86,-6,60,14,0,16)})
c.strokeStyle='#111';c.lineWidth=3
c.beginPath();c.moveTo(66,-40);c.quadraticCurveTo(70,-14,50,4);c.stroke()
c.beginPath();c.moveTo(42,22);c.quadraticCurveTo(48,38,36,48);c.stroke()
c.restore()
}
c.lineWidth=3
for(const d of[-1,1]){
const s=4*sin(T*t*2+d),x0=128+d*12,y0=88,cx=128+d*22,cy=48,x1=128+d*50+s,y1=32
c.beginPath();c.moveTo(x0,y0);c.quadraticCurveTo(cx,cy,x1,y1);c.stroke()
for(let k=1;k<=5;k++){
const u=k/6,px=(1-u)**2*x0+2*u*(1-u)*cx+u*u*x1,py=(1-u)**2*y0+2*u*(1-u)*cy+u*u*y1,l=12-k
c.beginPath();c.moveTo(px-d*l*.7,py-l*.7);c.lineTo(px,py);c.lineTo(px+d*l*.7,py+l*.7);c.stroke()
}
}
c.lineWidth=6
shape(()=>c.ellipse(128,172,20,38,0,0,T))
for(const[x,y,r]of[[110,134,14],[146,134,14],[128,142,16]])shape(()=>c.arc(x,y,r,0,T))
shape(()=>c.arc(128,110,30,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*15,108,7,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.ellipse(128+d*15,110,7,9,0,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(128,120,5,.2*PI,.8*PI);c.stroke()
for(const[y,w]of[[186,13],[198,10]])c.beginPath(),c.moveTo(128-w,y),c.quadraticCurveTo(128,y+5,128+w,y),c.stroke()
}
+34
View File
@@ -0,0 +1,34 @@
// slow loris on a branch: huge eyes in a dark mask, it slooowly stretches one arm up to the twig ahead, grips it and lets go, head tilting along, and blinks
const{sin,cos,PI,hypot}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const r=(1-cos(T*t))/2,bl=t>.06&&t<.12,hx=118+4*r,hy=112-2*r
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(0,-14)
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
const body=()=>c.ellipse(86,170,50,30,-.1,0,T)
c.lineWidth=16;c.beginPath();c.moveTo(24,205);c.quadraticCurveTo(128,186,232,197);c.stroke()
c.lineWidth=8;c.beginPath();c.moveTo(200,194);c.quadraticCurveTo(214,172,212,138);c.stroke()
c.lineWidth=6;shape(()=>c.ellipse(210,128,9,16,.3,0,T))
shape(body)
for(const x of[54,96])shape(()=>c.ellipse(x,196,11,9,0,0,T))
const sx=124,sy=156,ax=138+70*r,ay=186-18*r-34*sin(PI*r),qx=(sx+ax)/2+6+8*r,qy=(sy+ay)/2-6-10*r
const arm=(o,p)=>{c.beginPath();c.moveTo(sx+o,sy+p);c.quadraticCurveTo(qx+o,qy+p,ax+o,ay+p);c.stroke()}
c.lineWidth=14;arm(0,0)
let nx=-(ay-sy),ny=ax-sx;const n=hypot(nx,ny);nx/=n;ny/=n;if(nx*(86-sx)+ny*(170-sy)<0)nx=-nx,ny=-ny
c.save();c.beginPath();body();c.clip();c.strokeStyle='#111';c.lineWidth=3;arm(7.5*nx,7.5*ny);c.restore()
shape(()=>c.arc(ax,ay,10,0,T))
c.strokeStyle='#111';c.lineWidth=2.5;for(const d of[-4,4])c.beginPath(),c.moveTo(ax+d,ay-8),c.lineTo(ax+d,ay-2),c.stroke()
c.strokeStyle='#fff';c.lineWidth=6
c.save();c.translate(hx,hy);c.rotate(.2*r)
for(const d of[-1,1])shape(()=>c.arc(d*31,-16,8,0,T))
shape(()=>c.ellipse(0,0,38,34,0,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1]){c.beginPath();c.moveTo(d*8,-20);c.quadraticCurveTo(d*26,-20,d*26,-3);c.quadraticCurveTo(d*26,10,d*15,10);c.quadraticCurveTo(d*5,9,d*6,-4);c.closePath();c.fill()}
c.fillStyle=c.strokeStyle='#fff'
for(const d of[-1,1])if(bl)c.lineWidth=3,c.beginPath(),c.arc(d*16,-4,7,.2*PI,.8*PI),c.stroke()
else c.lineWidth=2,c.beginPath(),c.arc(d*16,-3,6.5,0,T),c.stroke(),c.beginPath(),c.arc(d*16+2.5,-5.5,3,0,T),c.fill()
c.fillStyle=c.strokeStyle='#111';c.beginPath();c.arc(0,16,3.5,0,T);c.fill()
c.lineWidth=3;c.beginPath();c.arc(-5,20,5,.15*PI,.85*PI);c.arc(5,20,5,.15*PI,.85*PI);c.stroke()
c.restore()
}
+28
View File
@@ -0,0 +1,28 @@
// snow leopard loafing: its thick spotted tail swishes in a slow S curve, an ear flicks back and it blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const s=sin(T*t),k=sin(T*t-1.2),bl=t>.78&&t<.84,tw=t>.36&&t<.44?-.4:0
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(10,-12)
const P=[[66,188],[20,200],[18+16*s,122],[46+24*k,86+8*s]]
const B=u=>[0,1].map(i=>(1-u)**3*P[0][i]+3*(1-u)**2*u*P[1][i]+3*(1-u)*u*u*P[2][i]+u**3*P[3][i])
c.lineWidth=26;c.beginPath();c.moveTo(...P[0]);c.bezierCurveTo(...P[1],...P[2],...P[3]);c.stroke()
c.lineWidth=6
shape(()=>c.ellipse(120,178,70,34,0,0,T))
for(const x of[164,200])shape(()=>c.ellipse(x,208,20,10,0,0,T))
c.save();c.translate(166,112);c.rotate(-.3+tw);shape(()=>c.ellipse(0,-4,11,13,0,0,T));c.restore()
c.save();c.translate(214,112);c.rotate(.3);shape(()=>c.ellipse(0,-4,11,13,0,0,T));c.restore()
shape(()=>c.ellipse(190,144,38,34,0,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const u of[.35,.55,.75,.92]){const[x,y]=B(u);c.beginPath();c.arc(x,y,5,0,T);c.fill()}
c.lineWidth=3
for(const[x,y]of[[76,170],[102,160],[96,188],[128,172],[152,160],[64,194],[124,196]])c.beginPath(),c.arc(x,y,6,.3,1.7*PI),c.stroke()
for(const[x,y]of[[182,122],[198,122],[190,114]])c.beginPath(),c.arc(x,y,2.5,0,T),c.fill()
for(const x of[164,200])c.beginPath(),c.moveTo(x+6,204),c.lineTo(x+6,212),c.moveTo(x+14,204),c.lineTo(x+14,212),c.stroke()
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(190+d*15,140,5.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(190+d*15,142,5.5,0,T),c.fill()
c.beginPath();c.moveTo(184,152);c.lineTo(196,152);c.lineTo(190,158);c.closePath();c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(190,158);c.lineTo(190,162);c.quadraticCurveTo(186,167,181,165);c.moveTo(190,162);c.quadraticCurveTo(194,167,199,165);c.stroke()
}
+20
View File
@@ -0,0 +1,20 @@
// stick insect: it rocks back and forth like a twig in the breeze with its feet planted, antennae swaying, it blinks
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const s=sin(T*t),dx=10*s,dy=-3*cos(T*t*2),bl=t>.62&&t<.68
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=5
c.translate(128,128);c.scale(.9,.9);c.translate(-128,-124)
for(const[hx,hy,kx,ky,fx]of[[64,156,34,176,18],[108,146,96,180,80],[150,136,180,166,200]])
c.beginPath(),c.moveTo(hx+dx,hy+dy),c.lineTo(kx+dx,ky+dy),c.lineTo(fx,210),c.stroke()
c.save();c.translate(dx,dy)
c.lineWidth=16;c.beginPath();c.moveTo(18,150);c.quadraticCurveTo(24,164,40,160);c.lineTo(176,128);c.stroke()
c.lineWidth=3;for(const i of[0,1])c.beginPath(),c.moveTo(202,104),c.bezierCurveTo(214,84-8*i,226+4*sin(T*t*2+i),74-10*i,244-10*i,66-18*i+5*sin(T*t+i*2)),c.stroke()
c.lineWidth=6;c.beginPath();c.ellipse(194,118,22,19,-.2,0,T);c.fill();c.stroke()
c.fillStyle=c.strokeStyle='#111'
c.lineWidth=3;for(const x of[64,108,150])c.beginPath(),c.moveTo(x-1,163-.235*(x-40)-8),c.lineTo(x+1,163-.235*(x-40)+5),c.stroke()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(201,111,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(201,113,6,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(205,122,5,.15*PI,.75*PI);c.stroke()
c.restore()
}
+36
View File
@@ -0,0 +1,36 @@
// stork flying with a bundle in its beak: its wings flap, it bobs, the bundle swings and the baby inside blinks
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const f=sin(T*t*2),a=.5+.85*f,sw=.18*sin(T*t*2-1.8),bl=t>.55&&t<.62
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(5,12)
c.translate(0,46-6*sin(T*t*2+1.2))
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
const wing=(x,y,r,k,ln)=>{
c.save();c.translate(x,y);c.rotate(r);c.scale(k,k)
c.beginPath();c.moveTo(14,6);c.bezierCurveTo(-10,-30,-74,-38,-108,-18)
c.quadraticCurveTo(-94,-8,-100,0);c.quadraticCurveTo(-86,0,-88,9);c.quadraticCurveTo(-74,8,-74,17);c.quadraticCurveTo(-60,14,-58,22);c.quadraticCurveTo(-24,24,14,6)
c.fill();c.stroke()
if(ln){c.strokeStyle='#111';c.lineWidth=3;for(const[x0,y0,x1,y1]of[[-100,0,-80,-17],[-88,9,-66,-10],[-74,17,-52,-2],[-58,22,-38,8]])c.beginPath(),c.moveTo(x0+3,y0-3),c.lineTo(x1,y1),c.stroke()}
c.restore()}
c.lineWidth=5;for(const[y,d]of[[118,0],[123,8]])c.beginPath(),c.moveTo(64,y),c.lineTo(30,y+8+d),c.stroke()
c.lineWidth=6
wing(130,94,a+.3,.82,0)
shape(()=>{c.moveTo(64,102);c.lineTo(34,92);c.lineTo(40,114);c.closePath()})
shape(()=>c.ellipse(104,108,56,30,-.1,0,T))
c.lineWidth=20;c.beginPath();c.moveTo(140,100);c.quadraticCurveTo(166,98,172,74);c.stroke();c.lineWidth=6
shape(()=>c.arc(176,70,18,0,T))
c.save();c.translate(204,83);c.rotate(sw)
shape(()=>{c.moveTo(-6,2);c.lineTo(-14,-12);c.lineTo(0,-4);c.lineTo(12,-14);c.lineTo(6,2)
c.bezierCurveTo(30,20,36,62,0,66);c.bezierCurveTo(-36,62,-30,20,-6,2)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3;c.beginPath();c.arc(0,42,14,0,T);c.stroke()
for(const d of[-1,1])if(bl)c.beginPath(),c.arc(d*5.5,40,3.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(d*5.5,41,3,0,T),c.fill()
c.beginPath();c.arc(0,46,4,.2*PI,.8*PI);c.stroke()
c.restore()
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
shape(()=>{c.moveTo(186,62);c.lineTo(229,86);c.lineTo(188,80);c.closePath()})
wing(118,98,a,1,1)
c.fillStyle='#111';c.beginPath();c.arc(180,66,5,0,T);c.fill()
}
+22
View File
@@ -0,0 +1,22 @@
// sugar glider sailing along: limbs spread wide, its skin flaps billow, it banks and bobs, its fluffy tail swishes and its big eyes blink
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const s=sin(T*t),b=6*sin(T*t*2),bl=t>.55&&t<.61
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(128,124+5*sin(T*t*2+.5));c.rotate(.1*s);c.scale(.94,.94);c.translate(-128,-124)
c.save();c.translate(128,168);c.rotate(.25*sin(T*t-1));shape(()=>c.ellipse(0,38,14,38,0,0,T));c.restore()
const P=[[52,88],[204,88],[68,186],[188,186]]
c.lineWidth=11;for(const[x,y]of P)c.beginPath(),c.moveTo(128,132),c.lineTo(x,y),c.stroke();c.lineWidth=6
shape(()=>{c.moveTo(52,88);c.quadraticCurveTo(86-b,136,68,186);c.quadraticCurveTo(128,166+b,188,186);c.quadraticCurveTo(170+b,136,204,88);c.quadraticCurveTo(128,96,52,88)})
shape(()=>c.ellipse(128,132,34,46,0,0,T))
for(const[x,y]of P)shape(()=>c.arc(x,y,8,0,T))
for(const d of[-1,1])shape(()=>c.ellipse(128+d*30,44,13,18,d*.5,0,T))
shape(()=>c.ellipse(128,74,34,30,0,0,T))
c.fillStyle=c.strokeStyle='#111'
c.beginPath();c.moveTo(122,46);c.lineTo(134,46);c.lineTo(129.5,66);c.lineTo(126.5,66);c.fill()
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*15,72,8,.15*PI,.85*PI),c.stroke()
else{c.fillStyle='#111';c.beginPath();c.arc(128+d*15,74,8.5,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(128+d*15+3,71,2.5,0,T);c.fill()}
c.fillStyle='#111';c.beginPath();c.ellipse(128,88,5,3.5,0,0,T);c.fill()
}
+19
View File
@@ -0,0 +1,19 @@
// ocean sunfish: a big round flat-backed mola sculling in place, its tall top and bottom fins sweep back and forth together, bubbles rise from its little o mouth
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const s=sin(T*t*2),bl=t>.6&&t<.67
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
for(const[i,x]of[0,14].entries()){const q=(t+i/2)%1;c.beginPath();c.arc(212+x*q+4*sin(T*q),118-80*q,6*sin(PI*q),0,T);c.fill()}
c.translate(128,128+6*sin(T*t));c.rotate(.04*sin(T*t));c.translate(-128,-128)
const fin=(y,d)=>{c.save();c.translate(112,y);c.rotate(d*(.32*s-.06));shape(()=>{c.moveTo(-22,8*d);c.quadraticCurveTo(-24,-36*d,-14,-56*d);c.quadraticCurveTo(-8,-64*d,-2,-56*d);c.quadraticCurveTo(10,-30*d,22,8*d)});c.restore()}
fin(82,1);fin(174,-1)
shape(()=>{c.moveTo(66,82);c.bezierCurveTo(110,58,190,66,200,122);c.bezierCurveTo(206,170,150,196,106,190)
c.bezierCurveTo(90,188,74,182,66,176);for(let i=0;i<4;i++){const y=176-i*23.5;c.quadraticCurveTo(52,y-12,66,y-23.5)}})
c.fillStyle=c.strokeStyle='#111'
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(174,110,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(174,112,6,0,T),c.fill()
c.lineWidth=3.5;c.beginPath();c.arc(200,134,4.5,0,T);c.stroke()
c.lineWidth=3;c.beginPath();c.moveTo(160,122);c.quadraticCurveTo(166,134,160,146);c.stroke()
}
+22
View File
@@ -0,0 +1,22 @@
// tadpole swimming in place: a wave runs down its tail, its new little back legs kick, it bobs and blows bubbles, and blinks
const{sin,cos,PI,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const bl=t>.7&&t<.76,kk=.5*sin(T*t*2)
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(0,16)
for(const i of[0,1]){const q=(t+i/2)%1;shape(()=>c.arc(206+8*sin(T*q)+10*q,104-86*q,4+5*q,0,T))}
c.translate(0,7*sin(T*t))
const N=24,P=[...Array(N+1)].map((_,i)=>{const u=i/N;return[118-96*u,130+18*u*sin(T*t*2-4*u),24*(1-u)**1.3+3]})
shape(()=>{for(const[x,y,w]of P)c.lineTo(x,y-w);for(const[x,y,w]of[...P].reverse())c.lineTo(x,y+w);c.closePath()})
c.lineWidth=7
for(const[x,y,p]of[[120,160,0],[136,166,PI]]){const a=.5+.5*sin(T*t*2+p)
c.beginPath();c.moveTo(x,y-10);c.lineTo(x-10,y+10);c.lineTo(x-20-8*a,y+8+10*a);c.stroke()}
c.lineWidth=6
shape(()=>c.ellipse(156,128,52,46,-.05,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const[x,y]of[[164,114],[196,118]])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(x,y-2,6.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(x,y,6.5,0,T),c.fill()
c.lineWidth=3.5;c.beginPath();c.arc(184,134,8,.2*PI,.8*PI);c.stroke()
}
+28
View File
@@ -0,0 +1,28 @@
// tarsier clinging to a branch: it swivels its head from side to side with its huge eyes, its big ears follow, its tail sways and it blinks
const{sin,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const h=sin(T*t),bl=t>.22&&t<.28
c.fillStyle=c.strokeStyle='#fff'
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.lineWidth=16;c.beginPath();c.moveTo(72,232);c.lineTo(84,24);c.stroke()
c.lineWidth=5;c.beginPath();c.moveTo(118,196);c.bezierCurveTo(128,238,172,240,186+6*sin(T*t),212);c.stroke()
c.lineWidth=6
shape(()=>c.ellipse(186+6*sin(T*t),206,6,11,.3,0,T))
shape(()=>c.ellipse(106,188,20,30,-.3,0,T))
shape(()=>c.ellipse(120,152,32,42,.15,0,T))
c.lineWidth=12;c.beginPath();c.moveTo(118,126);c.lineTo(88,118);c.moveTo(102,206);c.lineTo(82,212);c.stroke();c.lineWidth=6
for(const[x,y]of[[80,110],[76,122],[82,130],[76,206],[78,218]])shape(()=>c.arc(x,y,5,0,T))
c.save();c.translate(138,92);c.rotate(.12*h)
for(const d of[-1,1])shape(()=>c.ellipse(d*38-6*h,-30,16,20,d*.5,0,T))
shape(()=>c.ellipse(0,0,46,38,0,0,T))
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1]){
const x=d*19+10*h,r=15*(1+.12*d*h)
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(x,-4,r*.7,.15*PI,.85*PI),c.stroke()
else{c.fillStyle='#111';c.beginPath();c.ellipse(x,-2,r,16,0,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(x+4,-8,4,0,T);c.fill()}
}
c.fillStyle='#111';c.beginPath();c.ellipse(12*h,18,3.5,2.5,0,0,T);c.fill()
c.lineWidth=3;c.beginPath();c.arc(12*h,22,6,.25*PI,.75*PI);c.stroke()
c.restore()
}
+21
View File
@@ -0,0 +1,21 @@
// tsuchinoko, the chubby cryptid snake: it rocks back and forth on its round belly, stubby tail wagging, tongue flicking, it blinks
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const a=.17*sin(T*t),tg=t>.5&&t<.7?sin(PI*(t-.5)/.2):0,bl=t>.86&&t<.92
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=f=>{c.beginPath();f();c.fill();c.stroke()}
c.translate(128,128);c.scale(.92,.92);c.translate(-128,-140)
c.translate(120+46*a,154);c.rotate(a);c.translate(-120,-154)
c.lineWidth=8;c.beginPath();c.moveTo(60,160);c.quadraticCurveTo(32,166,20,148+6*sin(T*t*2));c.stroke();c.lineWidth=6
shape(()=>c.ellipse(114,154,70,46,0,0,T))
shape(()=>c.ellipse(184,140,20,22,-.3,0,T))
shape(()=>c.ellipse(204,124,30,20,-.18,0,T))
if(tg>0){c.lineWidth=3;const L=230+14*tg;c.beginPath();c.moveTo(228,130);c.lineTo(L,132);c.lineTo(L+6,126);c.moveTo(L,132);c.lineTo(L+6,138);c.stroke()}
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3.5
c.lineWidth=6;for(const x of[66,94,122,150]){const y=154-46*Math.sqrt(1-((x-114)/70)**2);c.beginPath();c.moveTo(x,y);c.quadraticCurveTo(x+7,y+12,x+3,y+24);c.stroke()}
c.lineWidth=3;c.beginPath();c.moveTo(60,178);c.quadraticCurveTo(112,206,172,170);c.stroke()
if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(208,116,6,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(208,118,6,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.moveTo(228,132);c.quadraticCurveTo(218,140,204,136);c.stroke()
}
+35
View File
@@ -0,0 +1,35 @@
// the white rabbit running late: he frets over his pocket watch as its hand whirls, taps his foot, an ear twitches, a sweat drop slides
const{sin,cos,PI,min,max}=Math,T=2*PI
export const frames=24,delay=80,rim=3,rimColor='#111'
export default(c,t)=>{
const tp=max(0,sin(T*t*3)),tw=t>.4&&t<.48?.3:0,bl=t>.8&&t<.86,sd=(t*2)%1
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
const shape=(x,y,r,f)=>{c.save();c.translate(x,y);c.rotate(r);c.beginPath();f();c.fill();c.stroke();c.restore()}
c.translate(128,140);c.scale(.9,.9);c.translate(-128,-128-3*tp)
shape(108,52,-.18,()=>c.ellipse(0,-6,12,34,0,0,T))
shape(142,52,.2+tw,()=>c.ellipse(0,-6,12,34,0,0,T))
shape(0,0,0,()=>c.ellipse(124,172,40,46,0,0,T))
shape(98,222,0,()=>c.ellipse(0,0,24,9,0,0,T))
shape(132,222+3*tp,-.35*tp,()=>c.ellipse(20,0,24,9,0,0,T))
shape(0,0,0,()=>c.ellipse(124,98,36,32,0,0,T))
c.lineWidth=11;c.beginPath();c.moveTo(156,152);c.lineTo(178,150);c.stroke();c.lineWidth=6
shape(194,150,0,()=>c.arc(0,0,26,0,T))
shape(194,120,0,()=>c.rect(-5,-5,10,7))
c.fillStyle=c.strokeStyle='#111';c.lineWidth=2.5
c.beginPath();c.arc(194,150,20,0,T);c.stroke()
for(let i=0;i<4;i++){const a=i*PI/2;c.beginPath();c.moveTo(194+15*cos(a),150+15*sin(a));c.lineTo(194+18*cos(a),150+18*sin(a));c.stroke()}
const h=T*t*2-PI/2;c.lineWidth=3;c.beginPath();c.moveTo(194,150);c.lineTo(194+13*cos(h),150+13*sin(h));c.stroke()
c.beginPath();c.arc(194,150,3,0,T);c.fill()
c.lineWidth=2;c.setLineDash([3,4]);c.beginPath();c.moveTo(186,176);c.quadraticCurveTo(160,196,132,170);c.stroke();c.setLineDash([])
c.strokeStyle='#111';c.fillStyle='#fff';c.lineWidth=3;c.beginPath();c.ellipse(176,154,9,8,0,0,T);c.fill();c.stroke()
c.fillStyle=c.strokeStyle='#111'
c.beginPath();c.moveTo(124,132);c.lineTo(110,124);c.lineTo(110,140);c.closePath();c.moveTo(124,132);c.lineTo(138,124);c.lineTo(138,140);c.closePath();c.fill()
for(const x of[124,124])c.beginPath(),c.arc(x,156,2.5,0,T),c.arc(x,170,2.5,0,T),c.fill()
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(124+d*14+4,94,5.5,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(124+d*14+4,96,5.5,0,T),c.fill()
c.lineWidth=3;for(const d of[-1,1])c.beginPath(),c.moveTo(124+d*8+4,81),c.lineTo(124+d*19+4,86),c.stroke()
c.beginPath();c.ellipse(130,106,4,3,0,0,T);c.fill()
c.beginPath();c.moveTo(124,114);c.quadraticCurveTo(130,110,136,114);c.stroke()
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=4
if(sd<.8){const y=76+24*sd,z=sin(PI*sd/.8);c.save();c.translate(82,y);c.scale(z,z);c.beginPath();c.moveTo(0,-8);c.quadraticCurveTo(7,2,0,6);c.quadraticCurveTo(-7,2,0,-8);c.fill();c.stroke();c.restore()}
}
+24
View File
@@ -0,0 +1,24 @@
// yukiusagi, a snow bunny mound with leaf ears and berry eyes: the leaves wiggle, it gives a little squish and blinks while snowflakes drift down
const{sin,cos,PI}=Math,T=2*PI
export const frames=24,delay=85,rim=3,rimColor='#111'
export default(c,t)=>{
const q=sin(T*t*2),bl=t>.62&&t<.68
c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
c.translate(0,11)
const shape=g=>{c.beginPath();g();c.fill();c.stroke()}
for(const[i,x]of[34,222,62,196].entries()){const p=(t+i/4)%1;c.beginPath();c.arc(x+8*sin(T*p),20+150*p,5*sin(PI*p),0,T);c.fill()}
c.lineWidth=6
c.translate(128,206);c.scale(1+.03*q,1-.04*q);c.translate(-128,-206)
for(const d of[-1,1]){
c.save();c.translate(128+d*22,116);c.rotate(d*(.42+.14*sin(T*t*2+(d>0?0:2))))
shape(()=>{c.moveTo(0,4);c.bezierCurveTo(-24,-20,-18,-62,0,-82);c.bezierCurveTo(18,-62,24,-20,0,4)})
c.fillStyle=c.strokeStyle='#111';c.lineWidth=3;c.beginPath();c.moveTo(0,0);c.lineTo(0,-70)
for(const y of[-22,-40,-56])c.moveTo(0,y),c.lineTo(-9,y-10),c.moveTo(0,y),c.lineTo(9,y-10)
c.stroke();c.restore();c.fillStyle=c.strokeStyle='#fff';c.lineWidth=6
}
shape(()=>{c.moveTo(46,206);c.bezierCurveTo(30,142,82,112,128,112);c.bezierCurveTo(174,112,226,142,210,206);c.closePath()})
c.fillStyle=c.strokeStyle='#111'
for(const d of[-1,1])if(bl)c.lineWidth=3.5,c.beginPath(),c.arc(128+d*28,156,7,.15*PI,.85*PI),c.stroke()
else c.beginPath(),c.arc(128+d*28,158,7.5,0,T),c.fill()
c.lineWidth=3;c.beginPath();c.arc(122,168,6,.1*PI,.9*PI);c.arc(134,168,6,.1*PI,.9*PI);c.stroke()
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 90 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 103 KiB

Some files were not shown because too many files have changed in this diff Show More