mirror of
https://github.com/direct-img/vibegif.direct-img.link.git
synced 2026-10-29 11:44:51 +00:00
Double the colored section with 50 more stickers
Animals (unicorn, flamingo, peacock, giraffe, chameleon, axolotl, capybara, otter, corgi, toucan), food (sushi, cupcake, popsicle, pancakes, strawberry, pineapple, blender, latte, cotton candy, fries), nature and space (sunset, aurora, comet, galaxy, sunflower, lotus, maple leaf, island, snow globe, clam), objects (lava lamp, cassette, vinyl, disco ball, neon sign, traffic light, crayon, watering can, pinata, arcade) and rides and luck (hot-air balloon, submarine, helicopter, roller coaster, ferris wheel, fire truck, soccer goal, crown, clover, maneki-neko). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
// arcade cabinet whose screen shows a blinking pixel face, joystick wiggling, buttons pressing, marquee lights chasing
|
||||
const{sin,cos,PI,floor}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
const CAB='#9775fa',CD='#7048e8',MQ='#ffd43b',BUL='#ffa94d',BEZ='#495057',SCR='#212529',PX='#69db7c',HT='#ff6b6b',PANEL='#4dabf7',PD='#1c7ed6',BTN=['#ffd43b','#69db7c'],COIN='#ffa94d'
|
||||
const FACE=['..........','..##..##..','..##..##..','..........','.#......#.','..######..']
|
||||
const BLINK=['..........','..........','..##..##..','..........','.#......#.','..######..']
|
||||
const HEART=['.#.#.','#####','.###.','..#..']
|
||||
const px=(c,rows,x,y,s,col)=>{c.fillStyle=col;rows.forEach((r,j)=>[...r].forEach((ch,k)=>{if(ch=='#')c.fillRect(x+k*s,y+j*s,s,s)}))}
|
||||
export default(c,t,i)=>{
|
||||
const js=sin(T*t*2),b=floor(t*4)%2,pr=(t*4)%1<.5
|
||||
const body=()=>{c.beginPath();c.roundRect(62,40,132,208,12)}
|
||||
c.fillStyle=CAB;body();c.fill();c.stroke()
|
||||
c.save();body();c.clip();c.fillStyle=CD;c.fillRect(62,40,12,208);c.fillRect(182,40,12,208);c.restore()
|
||||
c.lineWidth=5;for(const x of[74,182])c.beginPath(),c.moveTo(x,40),c.lineTo(x,248),c.stroke()
|
||||
c.lineWidth=7;body();c.stroke()
|
||||
c.fillStyle=MQ;c.beginPath();c.roundRect(52,12,152,44,12);c.fill();c.stroke()
|
||||
for(let k=0;k<5;k++){const lit=(k+floor(t*16))%5<2;c.fillStyle=lit?'#fff':BUL;c.lineWidth=4;c.beginPath();c.arc(80+k*24,34,7,0,T);c.fill();c.stroke()}
|
||||
c.lineWidth=7;c.fillStyle=BEZ;c.beginPath();c.roundRect(72,64,112,94,10);c.fill();c.stroke()
|
||||
c.fillStyle=SCR;c.beginPath();c.roundRect(80,72,96,78,6);c.fill()
|
||||
const fl=i==6
|
||||
px(c,i==11||i==12?BLINK:FACE,98,92,6,fl?'#fff':PX)
|
||||
if(floor(t*8)%2==0)px(c,HEART,84,76,3,HT)
|
||||
c.fillStyle='rgba(255,255,255,.06)';for(let y=74;y<150;y+=4)c.fillRect(80,y,96,1.5)
|
||||
c.lineWidth=7;c.fillStyle=PANEL;c.beginPath();c.moveTo(48,162);c.lineTo(208,162);c.lineTo(200,194);c.lineTo(56,194);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=PD;c.beginPath();c.ellipse(96,178,15,6,0,0,T);c.fill();c.lineWidth=5;c.stroke()
|
||||
const bx=96+12*js,by=150
|
||||
for(const[w,st]of[[10,'#111'],[4,'#ced4da']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(96,177),c.lineTo(bx,by),c.stroke()
|
||||
c.strokeStyle='#111';c.fillStyle=HT;c.lineWidth=5;c.beginPath();c.arc(bx,by,11,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(bx-4,by-4,3,0,T);c.fill()
|
||||
BTN.forEach((col,k)=>{const x=146+k*28,y=178-k*3,on=k==b&≺c.fillStyle=col;c.beginPath();c.ellipse(x,y+(on?2:0),11,on?5:7,0,0,T);c.fill();c.lineWidth=5;c.stroke()})
|
||||
c.fillStyle=COIN;c.lineWidth=6;c.beginPath();c.roundRect(104,206,48,32,6);c.fill();c.stroke()
|
||||
c.fillStyle='#343a40';for(const x of[114,136])c.beginPath(),c.roundRect(x,213,6,16,2),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// northern lights ripple over snowy hills inside a rounded night-sky sticker, stars twinkling
|
||||
// the dark sky gets a white rim so it doesn't vanish on dark backgrounds
|
||||
const{sin,max}=Math,T=2*Math.PI
|
||||
export const frames=16,delay=90
|
||||
const SKY='#2b3a7a',R=[['#b197fc','#e5dbff',62,3.1,.1],['#38d9a9','#c3fae8',82,1.7,-.08],['#69db7c','#d3f9d8',104,0,.05]]
|
||||
const spk=(c,x,y,s)=>{c.lineWidth=3;c.fillStyle='#fff';c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.2,-s*.2],[0,s,s*.2,s*.2],[-s,0,-s*.2,s*.2],[0,-s,-s*.2,-s*.2]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
const pine=(c,x,y)=>{
|
||||
c.fillStyle='#a9744f';c.lineWidth=5;c.beginPath();c.rect(x-4,y-6,8,12);c.fill();c.stroke()
|
||||
c.fillStyle='#2f9e44';for(const[w,y0,h]of[[18,-6,18],[14,-18,16],[10,-28,14]])c.beginPath(),c.moveTo(x-w,y+y0),c.lineTo(x,y+y0-h),c.lineTo(x+w,y+y0),c.closePath(),c.fill(),c.stroke()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const a=t*T,win=()=>{c.beginPath();c.roundRect(14,26,228,206,48)}
|
||||
win();c.lineWidth=18;c.strokeStyle='#fff';c.stroke();c.fillStyle=SKY;c.fill();c.strokeStyle='#111'
|
||||
c.save();win();c.clip()
|
||||
for(const[x,y,o]of[[46,52,0],[208,48,.35],[134,40,.7],[226,100,.2],[34,112,.55]])spk(c,x,y,2+4*max(0,sin((t+o)*2*T)))
|
||||
for(const[col,lt,b,p,sl]of R){
|
||||
const top=x=>b+(x-128)*sl+12*sin(x/38+p+a)+5*sin(x/17-p-2*a),h=x=>34+10*sin(x/29+p*2-a)
|
||||
c.beginPath();for(let x=0;x<=256;x+=8)c.lineTo(x,top(x));for(let x=256;x>=0;x-=8)c.lineTo(x,top(x)+h(x));c.closePath()
|
||||
c.fillStyle=col;c.fill();c.lineWidth=4;c.stroke()
|
||||
c.save();c.clip();c.strokeStyle=lt;c.lineWidth=3
|
||||
for(let x=14*t-14;x<270;x+=14){const y0=top(x);c.beginPath();c.moveTo(x,y0+6);c.lineTo(x,y0+h(x)*.72);c.stroke()}
|
||||
c.restore();c.strokeStyle='#111'
|
||||
}
|
||||
c.lineWidth=7
|
||||
for(const[x0,x1,px,py]of[[96,300,206,104],[-40,170,56,92]]){
|
||||
c.fillStyle='#fff';c.beginPath();c.moveTo(x0,250);c.quadraticCurveTo(px,py,x1,250);c.closePath();c.fill();c.stroke()
|
||||
c.strokeStyle='#a5d8ff';c.lineWidth=5;c.beginPath();c.moveTo(px-30,(250+py)/2+22);c.quadraticCurveTo(px-6,(250+py)/2+12,px+16,(250+py)/2+20);c.stroke();c.strokeStyle='#111';c.lineWidth=7
|
||||
}
|
||||
pine(c,190,186);pine(c,214,196);pine(c,58,182)
|
||||
c.restore();c.lineWidth=7;win();c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// pink axolotl waving a little hand, its feathery gill fronds wiggling, bubbles drifting up
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const PK='#faa2c1',PD='#f06595',PL='#ffdeeb',BL='#ff8fab',BU='#a5d8ff'
|
||||
export default(c,t)=>{
|
||||
const wv=sin(2*T*t),tl=.12*sin(T*t)
|
||||
const D=(wd,cl,f)=>{for(const[l,s]of[[wd,'#111'],[wd-10,cl]])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
for(const[x,y0,r,o]of[[204,0,9,0],[222,0,6,.4],[196,0,5,.75]]){const p=(t+o)%1,y=70-p*60;if(p<.85){c.fillStyle=BU;c.lineWidth=4;c.beginPath();c.arc(x+3*sin(p*T*2),y,r,0,T);c.fill();c.stroke();c.fillStyle='#fff';c.beginPath();c.arc(x+3*sin(p*T*2)-r*.35,y-r*.35,r*.25,0,T);c.fill()}}
|
||||
c.lineWidth=7
|
||||
c.save();c.translate(150,200);c.rotate(tl)
|
||||
c.fillStyle=PK;c.beginPath();c.moveTo(0,-14);c.quadraticCurveTo(70,-30,92,6);c.quadraticCurveTo(60,20,0,16);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=PL;c.beginPath();c.moveTo(20,-12);c.quadraticCurveTo(66,-24,84,0);c.quadraticCurveTo(60,-6,20,-4);c.closePath();c.fill()
|
||||
c.restore()
|
||||
c.fillStyle=PK;for(const[x,d]of[[96,-1],[160,1]])c.beginPath(),c.ellipse(x,226,15,10,d*.3,0,T),c.fill(),c.stroke()
|
||||
c.beginPath();c.ellipse(128,196,48,36,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=PL;c.beginPath();c.ellipse(128,206,28,20,0,0,T);c.fill()
|
||||
for(const d of[-1,1])for(let k=0;k<3;k++){
|
||||
const a=d*(-.55+k*.45)+.1*sin(2*T*t+k*1.3+(d>0?1:0)),bx=128+d*58,by=104+k*18-18
|
||||
c.save();c.translate(bx,by);c.rotate(d>0?a:PI+a)
|
||||
D(14,PD,()=>{c.moveTo(0,0);c.lineTo(36,0)})
|
||||
c.fillStyle=PD;c.lineWidth=4;for(const x of[12,24])for(const s of[-1,1])c.beginPath(),c.ellipse(x,s*7,5,3,s*.6,0,T),c.fill(),c.stroke()
|
||||
c.restore();c.lineWidth=7
|
||||
}
|
||||
c.fillStyle=PK;c.beginPath();c.ellipse(128,118,70,52,0,0,T);c.fill();c.stroke()
|
||||
for(const d of[-1,1]){c.fillStyle='#111';c.beginPath();c.arc(128+d*34,110,8,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(128+d*34-2,107,3,0,T);c.fill()}
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*46,128,10,6,0,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(104,126);c.quadraticCurveTo(128,146,152,126);c.stroke()
|
||||
c.fillStyle=PK;c.lineWidth=7
|
||||
c.beginPath();c.ellipse(92,192,12,9,.4,0,T);c.fill();c.stroke()
|
||||
c.save();c.translate(166,182);c.rotate(-.9+.35*wv)
|
||||
D(20,PK,()=>{c.moveTo(0,0);c.lineTo(30,0)})
|
||||
c.translate(36,0);c.fillStyle=PK
|
||||
c.lineWidth=5;for(const a of[-.7,0,.7])c.beginPath(),c.ellipse(cos(a)*9,sin(a)*9,6,4,a,0,T),c.fill(),c.stroke()
|
||||
c.beginPath();c.arc(0,0,9,0,T);c.fill();c.stroke()
|
||||
c.restore()
|
||||
for(const d of[-1,1])c.lineWidth=4,c.beginPath(),c.arc(224,138+d*12,10,-.6,.6),c.stroke()
|
||||
c.lineWidth=7
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// blender whirling a pink smoothie, fruit chunks circling in the vortex while the lid rattles and the base hums
|
||||
const{sin,cos,PI,exp}=Math,T=2*PI
|
||||
export const frames=16,delay=60
|
||||
const GL='#e7f5ff',SM='#f783ac',SL='#faa2c1',BA='#ff6b6b',BD='#e03131',LID='#b197fc',BL='#ffc9c9',FR=['#ff6b6b','#fff3bf','#69db7c','#748ffc','#ffa94d','#69db7c']
|
||||
const LV=[[96,34],[120,26],[142,18]]
|
||||
const jar=c=>{c.beginPath();c.moveTo(70,42);c.lineTo(186,42);c.lineTo(172,164);c.lineTo(84,164);c.closePath()}
|
||||
export default(c,t,i)=>{
|
||||
const sp=T*t*2,ly=i%2?-3:1,lr=i%2?.03:-.02
|
||||
for(const[w,s]of[[20,'#111'],[10,GL]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(182,66),c.lineTo(208,72),c.lineTo(204,128),c.lineTo(176,136),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
jar(c);c.fillStyle=GL;c.fill()
|
||||
const ch=(back)=>FR.forEach((col,k)=>{const[y,rx]=LV[k%3],a=sp+k*PI+(k%3)*1.1;if((sin(a)<0)!=back)return;const s=back?.75:1;c.save();c.translate(128+cos(a)*rx*1.6,y+sin(a)*6);c.rotate(a*2+k);c.scale(s,s);c.fillStyle=col;c.lineWidth=3.5;c.beginPath();c.roundRect(-7,-7,14,14,4);c.fill();c.stroke();c.restore()})
|
||||
c.save();jar(c);c.clip()
|
||||
c.fillStyle=SM;c.beginPath();c.moveTo(60,72);for(let x=60;x<=196;x+=4)c.lineTo(x,72+30*exp(-(((x-128)/22)**2))+2*sin(x/9-sp*2));c.lineTo(196,170);c.lineTo(60,170);c.closePath();c.fill();c.lineWidth=5;c.stroke()
|
||||
ch(true)
|
||||
c.strokeStyle=SL;c.lineWidth=5;for(const[y,rx]of LV)for(const o of[0,PI])c.beginPath(),c.ellipse(128,y,rx*1.6,7,0,sp+o+.3,sp+o+1.5),c.stroke()
|
||||
ch(false)
|
||||
c.strokeStyle='#fff';c.lineWidth=7;c.beginPath();c.moveTo(86,58);c.lineTo(94,146);c.stroke()
|
||||
c.restore();c.strokeStyle='#111';c.lineWidth=7;jar(c);c.stroke()
|
||||
c.lineWidth=4;for(const y of[72,98,124])c.beginPath(),c.moveTo(164-(y-42)*.11,y),c.lineTo(176-(y-42)*.11,y),c.stroke()
|
||||
c.lineWidth=7
|
||||
c.save();c.translate(128,36+ly);c.rotate(lr);c.fillStyle=LID;c.beginPath();c.roundRect(-66,-8,132,16,8);c.fill();c.stroke();c.beginPath();c.roundRect(-16,-20,32,14,6);c.fill();c.stroke();c.restore()
|
||||
c.fillStyle=BD;c.beginPath();c.roundRect(78,160,100,14,6);c.fill();c.stroke()
|
||||
c.fillStyle=BA;c.beginPath();c.roundRect(66,172,124,62,[12,12,18,18]);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24,192,6,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24-2,190,2.2,0,T),c.fill()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(128,206,7,8,0,0,T);c.fill()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*44,204,9,5,0,0,T),c.fill()
|
||||
c.lineWidth=4;['#fff','#ffd43b','#69db7c'].forEach((col,k)=>{c.fillStyle=k==Math.floor(t*3)?col:'#dee2e6';c.beginPath();c.arc(104+k*24,224,4.5,0,T);c.fill();c.stroke()})
|
||||
c.lineWidth=7
|
||||
for(const d of[-1,1])for(const[w,s]of[[9,'#111'],[4,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();const x=128+d*(i%2?78:82);c.moveTo(x,186);c.quadraticCurveTo(x+d*6,200,x,214);c.stroke()}
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// capybara soaking in a hot spring with a yuzu on its head, eyes shut in bliss, bobbing gently as steam curls up
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=100
|
||||
const SN='#d9a77a',BR='#c08552',BD='#8d6346',WA='#74c0fc',WL='#d0ebff',ST='#ced4da',SD='#adb5bd',YZ='#ffd43b',YD='#fab005',LF='#51cf66',BL='#ffa8a8'
|
||||
export default(c,t)=>{
|
||||
const b=Math.round(3*sin(T*t)),yw=.1*sin(T*t-.8)
|
||||
const D=(wd,cl,f)=>{for(const[l,s]of[[wd,'#111'],[wd-8,cl]])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
for(const[x,o]of[[56,0],[204,.5]]){const p=(t+o)%1,a=sin(PI*p)
|
||||
if(a>.15)D(12,'#fff',()=>{for(let k=0;k<=8;k++){const u=k/8;c.lineTo(x+7*sin(u*T+p*T),70-p*24-u*40)}})}
|
||||
c.fillStyle=ST
|
||||
for(const[x,y,rx,ry]of[[36,184,26,18],[220,182,28,20],[70,226,30,16],[188,228,32,16]])c.beginPath(),c.ellipse(x,y,rx,ry,0,0,T),c.fill(),c.stroke()
|
||||
c.fillStyle=WA;c.beginPath();c.ellipse(128,198,104,38,0,0,T);c.fill();c.stroke()
|
||||
c.save();c.translate(0,b)
|
||||
c.fillStyle=BR
|
||||
for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*40,84,11,9,0,0,T),c.fill(),c.stroke()
|
||||
c.beginPath();c.roundRect(68,80,120,130,[52,52,30,30]);c.fill();c.stroke()
|
||||
c.fillStyle=BD;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*40,85,5,4,0,0,T),c.fill()
|
||||
c.fillStyle=SN;c.beginPath();c.ellipse(128,156,40,28,0,0,T);c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
c.fillStyle=BD;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*14,148,6,4,0,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(128,152);c.lineTo(128,162);c.moveTo(116,166);c.quadraticCurveTo(128,172,140,166);c.stroke()
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(128+d*30,118,9,1.15*PI,1.85*PI),c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*44,132,8,5,0,0,T),c.fill()
|
||||
c.save();c.translate(128,70);c.rotate(yw)
|
||||
c.lineWidth=7;c.fillStyle=YZ;c.beginPath();c.ellipse(0,-14,26,22,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=YD;for(const[x,y]of[[-10,-20],[6,-8],[12,-22],[-4,-6]])c.beginPath(),c.arc(x,y,2,0,T),c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(-10,-24,6,4,-.5,0,T);c.fill()
|
||||
c.fillStyle=LF;c.lineWidth=5;c.beginPath();c.ellipse(10,-40,12,6,-.4,0,T);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(0,-36);c.lineTo(2,-42);c.stroke()
|
||||
c.restore()
|
||||
c.restore()
|
||||
c.lineWidth=7
|
||||
const wy=x=>196+3*sin(x/14+T*t*2)
|
||||
c.save();c.beginPath();c.ellipse(128,198,104,38,0,0,T);c.clip()
|
||||
c.fillStyle=WA;c.beginPath();c.moveTo(20,240);for(let x=20;x<=236;x+=4)c.lineTo(x,wy(x));c.lineTo(236,240);c.closePath();c.fill()
|
||||
c.beginPath();for(let x=60;x<=196;x+=4)c.lineTo(x,wy(x));c.stroke()
|
||||
c.strokeStyle=WL;c.lineWidth=4
|
||||
for(const[x,w]of[[96,22],[160,18],[128,34]]){const y=x==128?220:212;c.beginPath();c.moveTo(x-w,y);c.lineTo(x+w,y);c.stroke()}
|
||||
c.restore()
|
||||
c.strokeStyle='#111';c.lineWidth=7;c.beginPath();c.ellipse(128,198,104,38,0,0,T);c.stroke()
|
||||
c.fillStyle=ST;for(const[x,y,rx,ry]of[[70,226,30,16],[188,228,32,16]])c.beginPath(),c.ellipse(x,y,rx,ry,0,0,T),c.fill(),c.stroke()
|
||||
c.fillStyle=SD;for(const[x,y]of[[62,222],[196,224]])c.beginPath(),c.ellipse(x,y,8,4,0,0,T),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// cassette tape whose spinning reels are its eyes, tape ticking along between them, notes floating up
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const BODY='#4dabf7',BD='#1c7ed6',LAB='#fff9db',BAND='#ff6b6b',STR='#ffd43b',WIN='#495057',TAPE='#a9744f',TL='#d9a47c',BL='#faa2c1',NOTE=['#b197fc','#69db7c']
|
||||
const note=(c,x,y,s,col)=>{
|
||||
c.save();c.translate(x,y);c.scale(s,s);c.fillStyle=col
|
||||
for(const[w,st]of[[9,'#111'],[3,col]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(5,4),c.lineTo(5,-24),c.lineTo(17,-18),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.ellipse(0,5,8,6,-.4,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const a=T*t*2/3
|
||||
for(let k=0;k<2;k++){const p=(t+k/2)%1,s=p<.75?1:(1-p)*4;note(c,56+k*140+6*sin(p*T),58-p*40,s,NOTE[k])}
|
||||
c.lineWidth=7;c.fillStyle=BODY;c.beginPath();c.roundRect(22,56,212,146,18);c.fill();c.stroke()
|
||||
c.fillStyle='#e7f5ff';c.lineWidth=4;for(const[x,y]of[[38,72],[218,72],[38,186],[218,186]])c.beginPath(),c.arc(x,y,5,0,T),c.fill(),c.stroke()
|
||||
const lab=()=>{c.beginPath();c.roundRect(42,68,172,98,10)}
|
||||
c.fillStyle=LAB;lab();c.fill()
|
||||
c.save();lab();c.clip();c.fillStyle=BAND;c.fillRect(42,68,172,16);c.fillStyle=STR;c.fillRect(42,84,172,6);c.restore()
|
||||
c.lineWidth=5;lab();c.stroke();c.beginPath();c.moveTo(42,84);c.lineTo(214,84);c.stroke()
|
||||
const win=()=>{c.beginPath();c.roundRect(68,98,120,46,23)}
|
||||
c.fillStyle=WIN;win();c.fill()
|
||||
c.save();win();c.clip()
|
||||
c.fillStyle=TAPE;for(const x of[98,158])c.beginPath(),c.arc(x,121,19,0,T),c.fill()
|
||||
c.strokeStyle=TAPE;c.lineWidth=5;c.beginPath();c.moveTo(98,138);c.lineTo(158,138);c.stroke()
|
||||
c.strokeStyle=TL;c.lineWidth=2;for(let k=0;k<5;k++){const x=98+((k*12+t*24)%60);c.beginPath();c.moveTo(x,136);c.lineTo(x+4,136);c.stroke()}
|
||||
c.strokeStyle='#111'
|
||||
for(const x of[98,158]){
|
||||
c.save();c.translate(x,121);c.rotate(a)
|
||||
c.fillStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(0,0,12,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(let k=0;k<6;k++)c.save(),c.rotate(k*PI/3),c.fillRect(-1.5,-12,3,5),c.restore()
|
||||
c.beginPath();c.arc(0,0,4.5,0,T);c.fill()
|
||||
c.restore()
|
||||
}
|
||||
c.restore()
|
||||
c.lineWidth=5;win();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.arc(128,150,7,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*58,154,9,5,0,0,T),c.fill()
|
||||
c.lineWidth=7;c.fillStyle=BD;c.beginPath();c.moveTo(62,202);c.lineTo(78,176);c.lineTo(178,176);c.lineTo(194,202);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=WIN;for(const x of[100,156])c.beginPath(),c.arc(x,190,5,0,T),c.fill()
|
||||
c.beginPath();c.roundRect(120,184,16,12,3);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
// chameleon on a branch slowly shifting color, eyeing a buzzing fly, then snapping it up with its long tongue
|
||||
const{sin,cos,PI,min,max,hypot,atan2}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const RING=['#69db7c','#38d9a9','#4dabf7','#b197fc','#f783ac','#ffa94d','#ffd43b'],BR='#a9744f',LF='#51cf66',TG='#ff8fab'
|
||||
const hex=h=>[1,3,5].map(k=>parseInt(h.slice(k,k+2),16))
|
||||
const mix=(a,b,u,l=0)=>'rgb('+hex(a).map((v,k)=>Math.round((v+(hex(b)[k]-v)*u)*(1-l)+255*l)).join(',')+')'
|
||||
const ease=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
export default(c,t,i)=>{
|
||||
const q=t*RING.length,k=Math.floor(q),u=ease(q-k),A=RING[k%7],B=RING[(k+1)%7],col=mix(A,B,u),lit=mix(A,B,u,.45)
|
||||
const orb=s=>[222+12*cos(4*T*s),70+8*sin(8*T*s)]
|
||||
const D=(wd,cl,f)=>{for(const[l,s]of[[wd,'#111'],[wd-10,cl]])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
const M=[210,158],hit=orb(.52)
|
||||
let fly=null,tip=null,fs=1
|
||||
if(t<.42)fly=orb(t)
|
||||
else if(t<.52){const p=ease((t-.42)/.1);fly=orb(t);tip=[M[0]+(hit[0]-M[0])*p,M[1]+(hit[1]-M[1])*p]}
|
||||
else if(t<.64){const p=1-ease((t-.52)/.12);tip=[M[0]+(hit[0]-M[0])*p,M[1]+(hit[1]-M[1])*p];fly=tip}
|
||||
else if(t>=.8){const p=ease((t-.8)/.2),e=orb(1);fly=[236+(e[0]-236)*p,30+(e[1]-30)*p+4*sin(p*PI*2)];fs=.35+.65*p}
|
||||
const chew=t>.64&&t<.8?Math.abs(sin((t-.64)/.16*PI*2)):0
|
||||
D(20,BR,()=>{c.moveTo(12,206);c.quadraticCurveTo(128,196,246,200)})
|
||||
c.fillStyle=LF;c.beginPath();c.ellipse(40,218,14,7,.5,0,T);c.fill();c.stroke()
|
||||
D(20,col,()=>{c.moveTo(70,160);c.bezierCurveTo(40,170,30,200,52,206);c.bezierCurveTo(70,210,72,186,56,184)})
|
||||
for(const[x0,y0,x1]of[[92,170,84],[150,172,158]])D(16,col,()=>{c.moveTo(x0,y0);c.lineTo(x1,190);c.lineTo(x1+(x1>120?8:-8),202)})
|
||||
c.fillStyle=col
|
||||
const sil=()=>{c.beginPath();c.ellipse(118,150,58,32,-.05,0,T);c.moveTo(150,128);c.quadraticCurveTo(170,100,190,122);c.lineTo(214,150);c.quadraticCurveTo(214,170,190,172);c.lineTo(150,174);c.closePath()}
|
||||
sil();c.lineWidth=14;c.stroke();sil();c.fill();c.lineWidth=7
|
||||
c.save();sil();c.clip();c.fillStyle=lit
|
||||
for(const[x,y]of[[84,150],[112,146],[140,150]])c.beginPath(),c.ellipse(x,y,7,22,.25,0,T),c.fill()
|
||||
c.restore()
|
||||
c.lineWidth=5;c.beginPath();for(let k=0;k<6;k++)c.moveTo(70+k*16,121-(k%2?0:2)),c.lineTo(78+k*16,114);c.stroke()
|
||||
if(tip){D(11,TG,()=>{c.moveTo(M[0]-6,M[1]);c.lineTo(tip[0],tip[1])});c.fillStyle=TG;c.beginPath();c.arc(tip[0],tip[1],8,0,T);c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7}
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(212,156);c.quadraticCurveTo(200,164,186,160);c.stroke()
|
||||
if(chew){c.fillStyle=col;c.beginPath();c.ellipse(194,166,8+3*chew,5+2*chew,0,0,T);c.fill();c.stroke()}
|
||||
c.lineWidth=7
|
||||
const e=fly||orb(.9),ex=180,ey=138,a=atan2(e[1]-ey,e[0]-ex)
|
||||
c.fillStyle=col;c.beginPath();c.arc(ex,ey,17,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(ex+cos(a)*5,ey+sin(a)*5,9,0,T);c.fill();c.lineWidth=4;c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(ex+cos(a)*8,ey+sin(a)*8,4.5,0,T);c.fill();c.lineWidth=7
|
||||
if(fly){
|
||||
const[fx,fy]=fly,fl=i%2
|
||||
c.save();c.translate(fx,fy);c.scale(fs,fs);c.translate(-fx,-fy)
|
||||
c.fillStyle='#fff';c.lineWidth=4
|
||||
for(const d of[-1,1])c.beginPath(),c.ellipse(fx+d*8,fy-9-fl*3,9,5+fl*2,d*(.6+fl*.3),0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=10;c.strokeStyle='#fff';c.beginPath();c.ellipse(fx,fy,9,7,0,0,T);c.stroke();c.fillStyle='#111';c.fill()
|
||||
c.restore();c.strokeStyle='#111';c.lineWidth=7
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// smiling clam opens up to show off a shining pearl, then shuts again, bubbles rising behind it
|
||||
const{sin,cos,PI,max,abs}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const SH='#faa2c1',SHD='#f783ac',IN='#e64980',PL='#f3f0ff',BL='#ff8787',BU='#e7f5ff'
|
||||
const sm=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
const spk=(c,x,y,s)=>{c.lineWidth=3;c.fillStyle='#fff';c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.2,-s*.2],[0,s,s*.2,s*.2],[-s,0,-s*.2,s*.2],[0,-s,-s*.2,-s*.2]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const o=sm((t-.1)/.2)*(1-sm((t-.72)/.2)),up=48*o,sc=1-.3*o,rim=152
|
||||
for(let k=0;k<3;k++){const p=(t+k/3)%1,r=5+2*k,x=[54,204,186][k]+5*sin(p*T*2+k),y=150-p*140;if(p<.92){c.fillStyle=BU;c.lineWidth=4;c.beginPath();c.arc(x,y,r,0,T);c.fill();c.stroke();c.strokeStyle='#fff';c.lineWidth=2.5;c.beginPath();c.arc(x,y,r*.55,PI*1.1,PI*1.5);c.stroke();c.strokeStyle='#111'}}
|
||||
c.lineWidth=7
|
||||
if(up>1){
|
||||
const mouth=()=>{c.beginPath();c.ellipse(128,rim-up*.5,84,up*.5+8,0,0,T)}
|
||||
mouth();c.fillStyle=IN;c.fill();c.stroke()
|
||||
c.save();mouth();c.clip()
|
||||
c.fillStyle=PL;c.lineWidth=5;c.beginPath();c.arc(128,rim-10,22,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(120,rim-18,7,4.5,-.5,0,T);c.fill()
|
||||
c.restore()
|
||||
}
|
||||
c.lineWidth=7;c.beginPath()
|
||||
for(let k=0;k<=56;k++){const q=PI+PI*k/56,b=1+.045*abs(sin(7*(q-PI)));c.lineTo(128+88*b*cos(q),rim-up+76*b*sin(q)*sc)}
|
||||
c.quadraticCurveTo(128,rim-up+10,40,rim-up);c.closePath();c.fillStyle=SH;c.fill();c.stroke()
|
||||
c.strokeStyle=SHD;c.lineWidth=3.5
|
||||
for(const q of[1.2,1.35,1.5,1.65,1.8].map(v=>v*PI))c.beginPath(),c.moveTo(128+18*cos(q),rim-up-8+12*sin(q)*sc),c.lineTo(128+74*cos(q),rim-up+66*sin(q)*sc),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.beginPath();c.moveTo(40,rim);c.quadraticCurveTo(128,rim+18,216,rim)
|
||||
for(let k=0;k<=56;k++){const q=PI*k/56,b=1+.045*abs(sin(7*q));c.lineTo(128+88*b*cos(q),rim+68*b*sin(q))}
|
||||
c.closePath();c.fillStyle=SH;c.fill();c.stroke()
|
||||
c.strokeStyle=SHD;c.lineWidth=3.5
|
||||
for(const q of[.25,.36,.64,.75].map(v=>v*PI))c.beginPath(),c.moveTo(128+30*cos(q),rim+30*sin(q)),c.lineTo(128+76*cos(q),rim+60*sin(q)),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
const hap=o>.6
|
||||
c.fillStyle='#111';c.lineWidth=4.5
|
||||
for(const d of[-1,1])if(hap)c.beginPath(),c.arc(128+d*22,184,6,PI*1.15,PI*1.85),c.stroke();else c.beginPath(),c.arc(128+d*22,182,5,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(128,190,8,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*40,192,7,4,0,0,T),c.fill()
|
||||
if(o>.6)for(const[x,y,q]of[[100,rim-up-6,0],[160,rim-up+2,.5]])spk(c,x,y,(o-.6)/.4*(4+4*max(0,sin((t+q)*4*T))))
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// four-leaf clover spinning like a pinwheel on its stem with a smiling center, lucky sparkles twinkling around
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const L=['#69db7c','#51cf66'],V='#2f9e44',ST='#40c057',BL='#ffa8a8',SP='#ffd43b'
|
||||
const CX=128,CY=106
|
||||
const leaf=c=>{c.beginPath();c.moveTo(0,-4);c.bezierCurveTo(-30,-20,-46,-46,-30,-60);c.bezierCurveTo(-18,-70,-4,-64,0,-52);c.bezierCurveTo(4,-64,18,-70,30,-60);c.bezierCurveTo(46,-46,30,-20,0,-4);c.closePath()}
|
||||
const spark=(c,x,y,s)=>{c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.18,-s*.18],[0,s,s*.18,s*.18],[-s,0,-s*.18,s*.18],[0,-s,-s*.18,-s*.18]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
// leaves alternate two greens, so half a turn per loop lands every leaf on one of the same color
|
||||
for(const[w,s]of[[17,'#111'],[8,ST]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(CX,CY),c.quadraticCurveTo(CX+6,190,CX+30,236),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
c.fillStyle=SP;c.lineWidth=4
|
||||
for(const[x,y,o]of[[38,52,0],[220,62,.25],[218,178,.5],[40,172,.75]]){const s=11*max(0,sin(PI*((t*2+o)%1)));if(s>1.5)spark(c,x,y,s)}
|
||||
c.save();c.translate(CX,CY);c.rotate(t*PI)
|
||||
for(let k=0;k<4;k++){
|
||||
c.save();c.rotate(k*PI/2);leaf(c);c.fillStyle=L[k%2];c.lineWidth=7;c.fill();c.stroke()
|
||||
c.strokeStyle=V;c.lineWidth=4;c.beginPath();c.moveTo(0,-10);c.lineTo(0,-46);c.moveTo(0,-30);c.lineTo(-12,-42);c.moveTo(0,-30);c.lineTo(12,-42);c.stroke();c.strokeStyle='#111'
|
||||
c.strokeStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(-22,-50,8,PI*1.1,PI*1.6);c.stroke();c.strokeStyle='#111'
|
||||
c.restore()
|
||||
}
|
||||
c.restore()
|
||||
for(const[w,s]of[[10,'#111'],[3,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(CX,CY,92,-PI*.15+t*PI,PI*.15+t*PI),c.stroke(),c.beginPath(),c.arc(CX,CY,92,PI*.85+t*PI,PI*1.15+t*PI),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=6;c.fillStyle=L[0];c.beginPath();c.arc(CX,CY,18,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.ellipse(CX+d*6,CY-3,2.5,3.5,0,0,T),c.fill()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(CX+d*11,CY+4,4,2.5,0,0,T),c.fill()
|
||||
c.lineWidth=3;c.beginPath();c.arc(CX,CY+2,4,.2*PI,.8*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
// comet with a glowing smiley head bobbing in a small loop, its long striped tail swishing, sparks peeling off
|
||||
const{sin,cos,PI,max,hypot}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const L=[['#9775fa',1],['#4dabf7',.74],['#d0ebff',.46]],SC=['#ffd43b','#fff','#faa2c1'],HD='#ffd43b',HALO='#fff3bf',BL='#ff8787'
|
||||
const spk=(c,x,y,s,f)=>{c.lineWidth=3;c.fillStyle=f;c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.2,-s*.2],[0,s,s*.2,s*.2],[-s,0,-s*.2,s*.2],[0,-s,-s*.2,-s*.2]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const a=t*T,hx=84+8*cos(a),hy=170+6*sin(a),dx=236-hx,dy=24-hy,D=hypot(dx,dy),ux=dx/D,uy=dy/D,nx=-uy,ny=ux,sw=20*sin(a+.6)
|
||||
const cen=v=>{const w=1-v,mx=hx+ux*D*.5+nx*sw,my=hy+uy*D*.5+ny*sw;return[w*w*hx+2*v*w*mx+v*v*(hx+ux*D),w*w*hy+2*v*w*my+v*v*(hy+uy*D)]}
|
||||
for(const[col,f]of L){
|
||||
const A=[],B=[],n=24
|
||||
for(let j=0;j<=n;j++){const v=j/n*(.45+.55*f),[x,y]=cen(v),[x1,y1]=cen(v+.01),l=hypot(x1-x,y1-y),w=50*f*(1-v/(.45+.55*f))**.9;A.push([x-(y1-y)/l*w,y+(x1-x)/l*w]);B.unshift([x+(y1-y)/l*w,y-(x1-x)/l*w])}
|
||||
c.beginPath();for(const[x,y]of[...A,...B])c.lineTo(x,y);c.closePath();c.fillStyle=col;c.fill();c.lineWidth=f==1?7:3;c.stroke()
|
||||
}
|
||||
for(let k=0;k<5;k++){const p=(t+k/5)%1,v=.3+.12*k+p*.06,sd=k%2?1:-1,[x,y]=cen(v),o=sd*(40*(1-v)+10+p*26),s=10*sin(PI*p);if(s>1.5)spk(c,x+nx*o,y+ny*o,s,SC[k%3])}
|
||||
c.lineWidth=5;c.fillStyle=HALO;c.beginPath();c.arc(hx,hy,42,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=HD;c.beginPath();c.arc(hx,hy,30,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(hx+12,hy-14,7,4,-.6,0,T);c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(hx+d*10-2,hy+1,4.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(hx+d*10-3,hy-1,1.6,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(hx-2,hy+8,6,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(hx+d*19-2,hy+9,5,3,0,0,T),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// corgi seen from behind, fluffy heart-shaped butt wiggling side to side on stubby trotting legs, smiling back over its shoulder
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const OR='#ffa94d',OD='#f08c00',PK='#faa2c1',TG='#ff8fab',BL='#ffa8a8'
|
||||
export default(c,t)=>{
|
||||
const w=.1*sin(2*T*t),l1=max(0,sin(2*T*t)),l2=max(0,-sin(2*T*t))
|
||||
for(const[x,l]of[[112,l2],[164,l1]]){c.fillStyle=OR;c.beginPath();c.roundRect(x-13,196-l*8,26,34,10);c.fill();c.stroke();c.fillStyle='#fff';c.beginPath();c.ellipse(x,228-l*8,15,9,0,0,T);c.fill();c.stroke()}
|
||||
c.save();c.translate(138,214);c.rotate(w);c.translate(-138,-214)
|
||||
for(const[x,l]of[[92,l1],[184,l2]]){c.fillStyle=OR;c.beginPath();c.roundRect(x-15,186-l*10,30,40,12);c.fill();c.stroke();c.fillStyle='#fff';c.beginPath();c.ellipse(x,230-l*10,18,10,0,0,T);c.fill();c.stroke()}
|
||||
c.fillStyle=OR;c.beginPath();c.ellipse(138,140,76,66,0,0,T);c.fill();c.stroke()
|
||||
// the butt: two fluffy scalloped cheeks meeting in a heart
|
||||
const fluff=(x,y,r,n=10)=>{c.beginPath();c.moveTo(x+r,y);for(let k=0;k<n;k++){const a=(k+.5)/n*T,e=(k+1)/n*T;c.quadraticCurveTo(x+cos(a)*(r+9),y+sin(a)*(r+9),x+cos(e)*r,y+sin(e)*r)}c.closePath()}
|
||||
c.fillStyle='#fff'
|
||||
fluff(114,178,30);c.fill();c.stroke();fluff(162,178,30);c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(138,170,40,26,0,0,T);c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(138,166);c.quadraticCurveTo(136,190,138,206);c.stroke();c.lineWidth=7
|
||||
c.save();c.translate(138,124);c.rotate(.4*sin(4*T*t))
|
||||
c.fillStyle='#fff';fluff(0,-6,11,7);c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
c.restore()
|
||||
c.restore()
|
||||
c.save();c.translate(96,78);c.rotate(-.1+.05*sin(2*T*t+1))
|
||||
for(const[x,a]of[[-24,-.35],[22,.35]]){c.save();c.translate(x,-26);c.rotate(a);c.fillStyle=OR;c.beginPath();c.moveTo(-14,10);c.lineTo(0,-30);c.lineTo(14,10);c.closePath();c.fill();c.stroke();c.fillStyle=PK;c.beginPath();c.moveTo(-6,6);c.lineTo(0,-16);c.lineTo(6,6);c.closePath();c.fill();c.restore()}
|
||||
c.fillStyle=OR;c.beginPath();c.ellipse(0,0,40,34,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.moveTo(-6,-30);c.quadraticCurveTo(4,-30,6,-8);c.quadraticCurveTo(30,4,22,22);c.quadraticCurveTo(0,38,-22,22);c.quadraticCurveTo(-30,4,-8,-8);c.closePath();c.fill()
|
||||
c.save();c.beginPath();c.ellipse(0,0,40,34,0,0,T);c.lineWidth=7;c.stroke();c.restore()
|
||||
for(const d of[-1,1]){c.fillStyle='#111';c.beginPath();c.arc(d*16,-4,5.5,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(d*16-2,-6,2,0,T);c.fill()}
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(0,8,7,5,0,0,T);c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(-10,16);c.quadraticCurveTo(-5,22,0,16);c.quadraticCurveTo(5,22,10,16);c.stroke()
|
||||
c.fillStyle=TG;c.beginPath();c.moveTo(-6,20);c.lineTo(6,20);c.quadraticCurveTo(7,32,0,32);c.quadraticCurveTo(-7,32,-6,20);c.fill();c.lineWidth=4;c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(d*26,10,7,4,0,0,T),c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// cotton candy on a paper cone, its fluffy tufts swirling round and puffing while sparkles twinkle around it
|
||||
// all tufts are stroked wide in black first and filled after, so the cloud keeps a single outline
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const PK='#faa2c1',PD='#f783ac',BU='#a5d8ff',CN='#fff',ST='#f783ac',BL='#ff8fab',SPK='#ffd43b'
|
||||
const star=(c,x,y,s)=>{c.beginPath();for(let k=0;k<8;k++){const r=k%2?s*.38:s,a=k*PI/4;c.lineTo(x+cos(a)*r,y+sin(a)*r)}c.closePath();c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
c.fillStyle=CN;c.beginPath();c.moveTo(106,150);c.lineTo(150,150);c.lineTo(132,236);c.lineTo(124,236);c.closePath();c.fill()
|
||||
c.save();c.clip();c.strokeStyle=ST;c.lineWidth=7;for(let k=-3;k<5;k++)c.beginPath(),c.moveTo(100,160+k*22),c.lineTo(156,140+k*22),c.stroke();c.restore()
|
||||
c.beginPath();c.moveTo(106,150);c.lineTo(150,150);c.lineTo(132,236);c.lineTo(124,236);c.closePath();c.stroke()
|
||||
const tf=[...Array(11)].map((_,k)=>{const a=k*T/11+T*t;return[128+cos(a)*68,96+sin(a)*50,26+4*sin(2*T*t+k*1.9),k%3?PK:BU]})
|
||||
const blob=()=>{c.beginPath();c.ellipse(128,96,62,48,0,0,T);for(const[x,y,r]of tf)c.moveTo(x+r,y),c.arc(x,y,r,0,T)}
|
||||
c.lineWidth=16;blob();c.stroke();c.lineWidth=7
|
||||
for(const[x,y,r,col]of tf)c.fillStyle=col,c.beginPath(),c.arc(x,y,r,0,T),c.fill()
|
||||
c.fillStyle=PK;c.beginPath();c.ellipse(128,96,62,48,0,0,T);c.fill()
|
||||
c.strokeStyle=PD;c.lineWidth=4.5;for(const[r,o]of[[50,0],[50,PI],[34,1.6]])c.beginPath(),c.ellipse(128,96,r*1.2,r*.85,0,T*t*-1+o,T*t*-1+o+1.1),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*22,94,6,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*22-2,92,2.2,0,T),c.fill()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(128,104,9,0,PI);c.closePath();c.fill()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*40,110,9,5,0,0,T),c.fill()
|
||||
c.fillStyle=SPK;c.lineWidth=4
|
||||
;[[34,36],[222,42],[28,168],[226,160]].forEach(([x,y],k)=>{const s=14*max(0,sin(T*t*2+k*1.6));if(s>3)star(c,x,y,s)})
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// purple crayon with a face scribbling a rainbow loop-de-loop, lifting off, then the line wipes away as it floats back
|
||||
const{sin,cos,PI,min,max,floor}=Math,T=2*PI
|
||||
export const frames=24,delay=80
|
||||
const RB=['#ff6b6b','#ffa94d','#ffd43b','#69db7c','#4dabf7','#b197fc'],CR='#9775fa',CL='#d0bfff',CD='#7048e8',BL='#faa2c1'
|
||||
const X0=36,X1=158,Y0=186,B=17,W=4.25,NS=90
|
||||
const P=s=>[X0+(X1-X0)*s-B*sin(s*T*W),Y0-B*cos(s*T*W)+B*.3]
|
||||
const sm=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
const sparkle=(c,x,y,s)=>{c.fillStyle='#fff';c.lineWidth=3.5;c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.18,-s*.18],[0,s,s*.18,s*.18],[-s,0,-s*.18,s*.18],[0,-s,-s*.18,-s*.18]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
let from=0,to=1,tip,lift=0
|
||||
if(t<.68)to=t/.68,tip=P(to)
|
||||
else if(t<.78){const u=(t-.68)/.1;tip=P(1);lift=34*sm(u)}
|
||||
else{const u=sm((t-.78)/.18);from=min(1,(t-.78)/.16);const a=P(1),b=P(0);tip=[a[0]+(b[0]-a[0])*u,a[1]+(b[1]-a[1])*u];lift=34*(1-sm((t-.9)/.1))}
|
||||
if(to>from){
|
||||
const pts=[];for(let k=floor(from*NS);k<=to*NS;k++)pts.push([k/NS,...P(k/NS)]);pts.push([to,...P(to)])
|
||||
c.lineWidth=14;c.beginPath();for(const[,x,y]of pts)c.lineTo(x,y);c.stroke()
|
||||
c.lineWidth=7;for(let r=0;r<6;r++){const seg=pts.filter(([s])=>s>=r/6-.012&&s<=(r+1)/6+.012);if(seg.length<2)continue;c.strokeStyle=RB[r];c.beginPath();for(const[,x,y]of seg)c.lineTo(x,y);c.stroke()}
|
||||
c.strokeStyle='#111'
|
||||
}
|
||||
if(t>.68&&t<.84){const s=12*sin(PI*(t-.68)/.16),[x,y]=P(1);sparkle(c,x+20,y-24,s);sparkle(c,x-6,y-40,s*.6)}
|
||||
const wob=t<.68?.05*sin(8*T*t):0
|
||||
c.save();c.translate(tip[0],tip[1]-lift);c.rotate(.55+wob);c.lineWidth=6
|
||||
c.fillStyle=CR;c.beginPath();c.moveTo(-3,-2);c.quadraticCurveTo(0,1,3,-2);c.lineTo(12,-28);c.lineTo(-12,-28);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.roundRect(-15,-112,30,86,[4,4,3,3]);c.fill();c.stroke()
|
||||
c.fillStyle=CL;c.beginPath();c.rect(-15,-96,30,58);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const y of[-88,-46])c.beginPath(),c.moveTo(-15,y),c.lineTo(15,y),c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*6,-72,3.2,0,T),c.fill()
|
||||
c.lineWidth=3;c.beginPath();c.arc(0,-66,4.5,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(d*10,-63,3.5,2,0,0,T),c.fill()
|
||||
c.fillStyle=CD;c.lineWidth=5;c.beginPath();c.roundRect(-15,-118,30,10,4);c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// golden crown bobbing on a velvet cap, its jewels glinting one after another with little sparkles popping off
|
||||
const{sin,cos,PI,max,round}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const G='#ffd43b',GD='#fab005',VEL='#9775fa',PE='#fff'
|
||||
const J=[[86,92,7,'#f783ac'],[76,172,10,'#4dabf7'],[128,172,14,'#ff6b6b'],[180,172,10,'#69db7c'],[170,92,7,'#4dabf7']]
|
||||
const crown=c=>{c.beginPath();for(const[x,y]of[[52,156],[42,78],[66,118],[86,60],[107,110],[128,40],[149,110],[170,60],[190,118],[214,78],[204,156]])c.lineTo(x,y);c.closePath()}
|
||||
const spark=(c,x,y,s)=>{c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.18,-s*.18],[0,s,s*.18,s*.18],[-s,0,-s*.18,s*.18],[0,-s,-s*.18,-s*.18]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const b=round(4*sin(t*T)),g=t*5|0,gp=t*5%1
|
||||
c.translate(0,b)
|
||||
c.fillStyle=VEL;c.beginPath();c.ellipse(128,124,74,58,0,PI,0);c.lineTo(202,150);c.lineTo(54,150);c.closePath();c.fill();c.stroke()
|
||||
crown(c);c.fillStyle=G;c.fill()
|
||||
c.save();crown(c);c.clip();c.fillStyle=GD;for(const[x,y]of[[42,78],[128,40],[214,78]])c.beginPath(),c.moveTo(x,y),c.lineTo(x+22,y+80),c.lineTo(x+6,y+90),c.closePath(),c.fill();c.restore()
|
||||
crown(c);c.stroke()
|
||||
c.lineWidth=5;c.fillStyle=PE;for(const[x,y]of[[42,78],[86,60],[128,40],[170,60],[214,78]])c.beginPath(),c.arc(x,y-4,9,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=GD;c.beginPath();c.roundRect(38,146,180,48,12);c.fill();c.stroke()
|
||||
c.fillStyle=G;c.beginPath();c.roundRect(44,152,168,10,5);c.fill()
|
||||
for(const[k,[x,y,s,col]]of J.entries()){
|
||||
c.lineWidth=5;c.fillStyle=col;c.beginPath()
|
||||
if(k==2)c.ellipse(x,y,s,s*.8,0,0,T);else c.moveTo(x,y-s),c.lineTo(x+s*.8,y),c.lineTo(x,y+s),c.lineTo(x-s*.8,y),c.closePath()
|
||||
c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(x-s*.3,y-s*.3,s*.22,s*.3,-.5,0,T);c.fill()
|
||||
if(k==g){const s2=4+12*sin(PI*gp);c.fillStyle='#fff';c.lineWidth=4;spark(c,x+s*.6,y-s*.7,s2)}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// cupcake with a swirl of pink frosting, sprinkles raining down onto it and the cherry on top wobbling
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
const WR='#38d9a9',WD='#0ca678',FR='#faa2c1',CH='#ff6b6b',STEM='#a9744f',BL='#ffa8a8',SP=['#ffd43b','#4dabf7','#fff','#69db7c','#b197fc','#ff922b']
|
||||
const rod=(c,x,y,a,col)=>{for(const[w,s]of[[9,'#111'],[4,col]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x-cos(a)*6,y-sin(a)*6),c.lineTo(x+cos(a)*6,y+sin(a)*6),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
export default(c,t)=>{
|
||||
c.fillStyle=WR;c.beginPath();c.moveTo(58,150);c.lineTo(198,150);c.lineTo(178,234);c.lineTo(78,234);c.closePath();c.fill();c.stroke()
|
||||
c.strokeStyle=WD;c.lineWidth=5;for(let k=1;k<6;k++)c.beginPath(),c.moveTo(58+k*140/6,158),c.lineTo(78+k*100/6,228),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24,190,10,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24,190,6,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24-2,188,2.2,0,T),c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(128,200,9,.15*PI,.85*PI);c.closePath();c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*44,204,9,5,0,0,T),c.fill()
|
||||
c.fillStyle=FR;for(const[y,rx,ry]of[[144,84,24],[116,66,22],[90,46,20]])c.beginPath(),c.ellipse(128,y,rx,ry,0,0,T),c.fill(),c.stroke()
|
||||
c.beginPath();c.moveTo(108,84);c.quadraticCurveTo(116,58,132,60);c.quadraticCurveTo(150,66,148,86);c.closePath();c.fill();c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=5;for(const[y,rx,ry]of[[144,72,14],[116,54,13],[90,34,11]])c.beginPath(),c.ellipse(128,y-2,rx,ry,0,PI*1.12,PI*1.32),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
;[[90,154,.5],[118,162,-.6],[152,158,.9],[176,146,-.3],[74,140,1.2],[104,128,-1],[142,130,.4],[166,118,-.8],[112,104,.7],[140,100,-.2],[92,112,.2]].forEach(([x,y,a],k)=>rod(c,x,y,a,SP[k%6]))
|
||||
c.save();c.translate(128,66);c.rotate(.3*sin(2*T*t))
|
||||
for(const[w,s]of[[9,'#111'],[4,STEM]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(0,-24),c.quadraticCurveTo(2,-42,12,-50),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111';c.fillStyle=CH;c.beginPath();c.arc(0,-12,15,0,T);c.fill();c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=4;c.beginPath();c.arc(0,-12,8,PI*1.1,PI*1.45);c.stroke()
|
||||
c.restore();c.strokeStyle='#111';c.lineWidth=7
|
||||
;[[84,128],[104,104],[152,102],[176,126],[120,86],[164,112]].forEach(([x,land],k)=>{const p=(t+k/6)%1;rod(c,x+4*sin(p*T+k),12+p*(land-12),k+p*9,SP[(k+2)%6])})
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// mirror disco ball spinning on its chain, tiles catching the light, colored light spots blinking around it
|
||||
// the tile colors repeat every 4 columns and the ball turns 4 columns per loop, so the loop is seamless
|
||||
const{sin,cos,PI,max,min,floor}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
const TL=['#e7f5ff','#d0bfff','#c5f6fa','#ffdeeb'],TD=['#a5d8ff','#b197fc','#66d9e8','#faa2c1'],SP=['#ff6b6b','#ffd43b','#69db7c','#4dabf7','#b197fc','#f783ac']
|
||||
const star=(c,x,y,s,col)=>{c.fillStyle=col;c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.18,-s*.18],[0,s,s*.18,s*.18],[-s,0,-s*.18,s*.18],[0,-s,-s*.18,-s*.18]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t,i)=>{
|
||||
const cx=128,cy=140,R=76,M=16,N=8,cw=T/M,rot=T*t/4
|
||||
for(let k=0;k<8;k++){
|
||||
const a=k*T/8+.39,r=104,on=(floor(t*8)+k*3)%4!=0
|
||||
if(on){c.lineWidth=4;star(c,cx+cos(a)*r,cy+sin(a)*r*.92,k%2?9:12,SP[k%6])}
|
||||
}
|
||||
for(const[w,st]of[[11,'#111'],[4,'#ced4da']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(cx,0),c.lineTo(cx,58),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle='#ced4da';c.beginPath();c.roundRect(cx-15,52,30,14,4);c.fill();c.stroke()
|
||||
c.fillStyle=TD[0];c.lineWidth=7;c.beginPath();c.arc(cx,cy,R,0,T);c.fill()
|
||||
c.save();c.beginPath();c.arc(cx,cy,R,0,T);c.clip()
|
||||
const P=(lo,la)=>[cx+R*cos(la)*sin(lo),cy+R*sin(la)]
|
||||
c.lineWidth=1.5;c.strokeStyle='#495057'
|
||||
for(let l=0;l<N;l++){
|
||||
const la0=-PI/2+l*PI/N,la1=la0+PI/N,lm=(la0+la1)/2
|
||||
for(let j=0;j<M;j++){
|
||||
let lo0=j*cw+rot-PI,lo1=lo0+cw
|
||||
lo0=((lo0+PI)%T+T)%T-PI;lo1=lo0+cw
|
||||
if(lo1<-PI/2||lo0>PI/2)continue
|
||||
const a0=max(lo0,-PI/2),a1=min(lo1,PI/2),lm2=(a0+a1)/2
|
||||
const lit=cos(lm2)*cos(lm)*.7-sin(lm2)*cos(lm)*.35-sin(lm)*.45,ci=(j+l*2)%4
|
||||
c.fillStyle=lit>.62?'#fff':lit>.25?TL[ci]:TD[ci]
|
||||
c.beginPath();for(const[lo,la]of[[a0,la0],[a1,la0],[a1,la1],[a0,la1]])c.lineTo(...P(lo,la));c.closePath();c.fill();c.stroke()
|
||||
}
|
||||
}
|
||||
c.restore();c.strokeStyle='#111'
|
||||
c.lineWidth=7;c.beginPath();c.arc(cx,cy,R,0,T);c.stroke()
|
||||
c.lineWidth=3
|
||||
for(const[x,y,p]of[[100,112,0],[156,154,.33],[116,178,.66]]){const s=13*max(0,sin(T*(2*t+p)));if(s>2)star(c,x,y,s,'#fff')}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// ferris wheel slowly turning, its candy-colored gondolas hanging upright, a smiling hub
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=100
|
||||
const G=['#ff6b6b','#ffd43b','#4dabf7','#69db7c'],RIM='#b197fc',LEG='#f783ac',BASE='#a9744f',HUB='#ffd43b',BL='#ffa8a8'
|
||||
const CX=128,CY=104,R=78
|
||||
export default(c,t)=>{
|
||||
// turning by half a revolution per loop lines gondola k up with gondola k+4, which has the same color
|
||||
const a0=t*PI
|
||||
for(const[w,s]of[[16,'#111'],[8,LEG]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(72,232),c.lineTo(CX,CY),c.lineTo(184,232),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle=BASE;c.beginPath();c.roundRect(44,226,168,16,8);c.fill();c.stroke()
|
||||
for(let k=0;k<8;k++){const a=a0+k*PI/4;for(const[w,s]of[[9,'#111'],[3,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(CX,CY),c.lineTo(CX+R*cos(a),CY+R*sin(a)),c.stroke()}
|
||||
for(const[w,s]of[[16,'#111'],[8,RIM]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(CX,CY,R,0,T),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
for(let k=0;k<8;k++){
|
||||
const a=a0+k*PI/4,x=CX+R*cos(a),y=CY+R*sin(a)
|
||||
c.save();c.translate(x,y)
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(0,0);c.lineTo(0,9);c.stroke()
|
||||
c.lineWidth=5;c.fillStyle=G[k%4];c.beginPath();c.roundRect(-14,8,28,22,7);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.roundRect(-9,13,18,8,3);c.fill();c.lineWidth=3;c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
c.lineWidth=6;c.fillStyle=HUB;c.beginPath();c.arc(CX,CY,17,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(CX+d*6,CY-3,2.5,0,T),c.fill()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(CX+d*10,CY+4,3.5,2.5,0,0,T),c.fill()
|
||||
c.lineWidth=3;c.beginPath();c.arc(CX,CY+2,4,.2*PI,.8*PI);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// fire truck rumbling along with its siren flashing red and blue, ladder bobbing, wheels turning, road dashes rolling past
|
||||
const{sin,cos,PI,abs,round}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const RD='#ff6b6b',RDD='#e03131',WIN='#a5d8ff',TIRE='#343a40',HUB='#ced4da',LAD='#dee2e6',SB='#4dabf7',SR='#fa5252',G='#ffd43b',BL='#ffa8a8'
|
||||
export default(c,t,i)=>{
|
||||
const b=-round(3*abs(sin(2*T*t))),rot=t*T,red=(i>>1)%2==0,la=-.05-.04*sin(2*T*t+1)
|
||||
c.fillStyle='#868e96';c.beginPath();c.roundRect(4,214,248,22,11);c.fill();c.stroke()
|
||||
c.save();c.beginPath();c.rect(10,214,236,22);c.clip()
|
||||
for(let k=-1;k<5;k++){const x=k*64-((t*128)%64)+20;c.fillStyle='#fff';c.beginPath();c.roundRect(x,222,30,6,3);c.fill()}
|
||||
c.restore()
|
||||
c.translate(0,b)
|
||||
c.save();c.translate(34,104);c.rotate(la)
|
||||
for(const[w,s]of[[11,'#111'],[4,LAD]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(0,0),c.lineTo(136,0),c.moveTo(0,-14),c.lineTo(136,-14),c.stroke()
|
||||
c.lineWidth=4;c.strokeStyle='#111';c.beginPath();for(let x=12;x<136;x+=16)c.moveTo(x,0),c.lineTo(x,-14);c.stroke()
|
||||
c.restore();c.lineWidth=7
|
||||
c.fillStyle=RD;c.beginPath();c.roundRect(24,108,144,76,8);c.fill();c.stroke()
|
||||
c.beginPath();c.moveTo(160,184);c.lineTo(160,96);c.quadraticCurveTo(160,86,170,86);c.lineTo(204,86);c.quadraticCurveTo(214,86,220,96);c.lineTo(232,128);c.lineTo(232,184);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=WIN;c.lineWidth=5;c.beginPath();c.moveTo(174,98);c.lineTo(206,98);c.lineTo(218,126);c.lineTo(174,126);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(184,108,3,7,.4,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.rect(24,150,208,10);c.fill();c.beginPath();c.moveTo(24,150);c.lineTo(232,150);c.moveTo(24,160);c.lineTo(232,160);c.stroke()
|
||||
c.lineWidth=5;c.beginPath();for(const x of[72,120])c.moveTo(x,116),c.lineTo(x,146);c.moveTo(166,134);c.lineTo(166,180);c.stroke()
|
||||
c.fillStyle=G;c.beginPath();c.arc(48,130,13,0,T);c.fill();c.stroke();c.beginPath();c.arc(48,130,5,0,T);c.stroke()
|
||||
c.fillStyle=G;c.lineWidth=5;c.beginPath();c.roundRect(222,132,14,12,4);c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(206,140,4,0,T);c.fill()
|
||||
c.fillStyle=BL;c.beginPath();c.ellipse(198,170,7,4,0,0,T);c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(214,166,6,.2*PI,.8*PI);c.stroke()
|
||||
c.lineWidth=5;c.fillStyle='#ced4da';c.beginPath();c.roundRect(176,76,32,10,4);c.fill();c.stroke()
|
||||
for(const[d,on,col,dim]of[[-1,red,SR,'#c92a2a'],[1,!red,SB,'#1c7ed6']]){
|
||||
c.fillStyle=on?col:dim;c.beginPath();c.moveTo(192,76);c.arc(192,76,14,d<0?PI:PI*1.5,d<0?PI*1.5:0);c.closePath();c.fill();c.stroke()
|
||||
if(on)for(const a of[-.5,-.15,.2].map(v=>d<0?PI+v+.35:-v-.35))for(const[w,s]of[[9,'#111'],[4,col]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(192+cos(a)*22,76+sin(a)*22),c.lineTo(192+cos(a)*34,76+sin(a)*34),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5
|
||||
}
|
||||
c.fillStyle='#fff';c.beginPath();c.ellipse(187,69,2.5,4,-.5,0,T);c.fill()
|
||||
for(const x of[64,112,196]){
|
||||
c.lineWidth=7;c.fillStyle=TIRE;c.beginPath();c.arc(x,190,22,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=HUB;c.beginPath();c.arc(x,190,10,0,T);c.fill();c.lineWidth=4;c.stroke()
|
||||
for(let k=0;k<4;k++){const a=rot+k*PI/2;c.beginPath();c.moveTo(x+cos(a)*4,190+sin(a)*4);c.lineTo(x+cos(a)*9,190+sin(a)*9);c.stroke()}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// flamingo standing on one leg, wobbling to keep its balance while its neck sways the other way
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const PK='#f783ac',PL='#faa2c1',PD='#e64980',LG='#ff8fab',WA='#74c0fc',WL='#d0ebff',BL='#ff6b6b'
|
||||
export default(c,t)=>{
|
||||
const a=.07*sin(T*t),n=-.12*sin(T*t-.5)
|
||||
const D=(wd,col,f)=>{for(const[l,s]of[[wd,'#111'],[wd-10,col]])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
c.fillStyle=WA;c.beginPath();c.ellipse(128,234,70,14,0,0,T);c.fill();c.stroke()
|
||||
c.strokeStyle=WL;c.lineWidth=4;c.beginPath();c.ellipse(128,234,30+6*sin(2*T*t),6,0,0,T);c.stroke();c.strokeStyle='#111';c.lineWidth=7
|
||||
c.save();c.translate(128,232);c.rotate(a);c.translate(-128,-232)
|
||||
D(17,LG,()=>{c.moveTo(128,232);c.lineTo(126,186);c.lineTo(122,150)})
|
||||
D(17,LG,()=>{c.moveTo(134,150);c.lineTo(156,180);c.lineTo(126,186)})
|
||||
c.fillStyle=LG;c.beginPath();c.ellipse(132,234,18,6,0,0,T);c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
c.fillStyle=PK;c.beginPath();c.moveTo(64,118);c.lineTo(38,108);c.lineTo(50,128);c.lineTo(36,138);c.lineTo(66,136);c.closePath();c.fill();c.stroke()
|
||||
c.beginPath();c.ellipse(112,128,56,34,-.12,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=PD;c.beginPath();c.moveTo(78,116);c.quadraticCurveTo(116,96,146,118);c.quadraticCurveTo(118,148,78,116);c.fill();c.lineWidth=5;c.stroke()
|
||||
c.beginPath();c.moveTo(96,120);c.quadraticCurveTo(112,112,128,122);c.stroke();c.lineWidth=7
|
||||
c.save();c.translate(150,112);c.rotate(n)
|
||||
D(26,PK,()=>{c.moveTo(0,0);c.bezierCurveTo(30,-18,-18,-50,2,-74)})
|
||||
c.translate(2,-80)
|
||||
c.fillStyle=PK;c.beginPath();c.arc(0,0,20,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.moveTo(14,-8);c.quadraticCurveTo(36,-6,40,8);c.lineTo(30,22);c.quadraticCurveTo(26,8,12,8);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.moveTo(36,2);c.quadraticCurveTo(44,12,32,30);c.quadraticCurveTo(30,20,28,16);c.closePath();c.fill();c.lineWidth=4;c.strokeStyle='#fff';c.stroke();c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle='#111';c.beginPath();c.arc(2,-4,4.5,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(0.5,-5.5,1.6,0,T);c.fill()
|
||||
c.fillStyle=BL;c.beginPath();c.ellipse(-4,8,6,4,0,0,T);c.fill()
|
||||
c.restore()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// french fries in a red carton bobbing and wiggling one after another like a wave, salt specks drifting down
|
||||
const{sin,PI,max}=Math,T=2*PI
|
||||
export const frames=20,delay=70
|
||||
const FY='#ffd43b',FD='#f59f00',CA='#ff6b6b',CB='#e03131',BL='#ffc9c9',PK='#ff8fab'
|
||||
const FR=[[90,48],[118,40],[146,42],[172,52],[104,64],[132,58],[160,66]]
|
||||
export default(c,t)=>{
|
||||
;[[96,0],[138,.33],[164,.66]].forEach(([x,o])=>{const p=(t+o)%1;c.fillStyle='#fff';c.lineWidth=2.5;c.save();c.translate(x+4*sin(T*p*2),8+p*56);c.rotate(p*6);c.beginPath();c.rect(-3,-3,6,6);c.fill();c.stroke();c.restore()})
|
||||
c.lineWidth=7
|
||||
c.fillStyle=CB;c.beginPath();c.moveTo(60,128);c.quadraticCurveTo(128,100,196,128);c.lineTo(196,150);c.lineTo(60,150);c.closePath();c.fill();c.stroke()
|
||||
FR.forEach(([x,top],k)=>{
|
||||
const ph=T*t*2-k*.9,dy=-14*max(0,sin(ph)),r=(x-128)/420+.1*sin(ph)
|
||||
c.save();c.translate(x,150+dy);c.rotate(r);const L=150-top
|
||||
c.fillStyle=FY;c.beginPath();c.roundRect(-9,-L,18,L+30,4);c.fill()
|
||||
c.fillStyle=FD;c.fillRect(3,-L+4,6,L+24);c.beginPath();c.roundRect(-9,-L,18,8,4);c.fill()
|
||||
c.beginPath();c.roundRect(-9,-L,18,L+30,4);c.stroke()
|
||||
c.fillStyle='#fff';for(const[sx,sy]of[[-4,-L+18],[0,-L+34]])c.fillRect(sx,sy+(k%3)*4,3,3)
|
||||
c.restore()
|
||||
})
|
||||
c.fillStyle=CA;c.beginPath();c.moveTo(54,124);c.quadraticCurveTo(128,156,202,124);c.lineTo(180,236);c.lineTo(76,236);c.closePath();c.fill();c.stroke()
|
||||
c.strokeStyle=CB;c.lineWidth=5;c.beginPath();c.moveTo(68,150);c.quadraticCurveTo(128,176,188,150);c.stroke();c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24,186,6,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24-2,184,2.2,0,T),c.fill()
|
||||
const mo=.55+.45*max(0,sin(T*t*4)),mouth=()=>{c.beginPath();c.moveTo(116,196);c.lineTo(140,196);c.bezierCurveTo(140,196+18*mo,116,196+18*mo,116,196);c.closePath()}
|
||||
c.fillStyle='#111';mouth();c.fill()
|
||||
c.save();mouth();c.clip();c.fillStyle=PK;c.beginPath();c.ellipse(128,196+14*mo,7,5,0,0,T);c.fill();c.restore()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*44,198,9,5,0,0,T),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// spiral galaxy turning on a round night-sky sticker, two candy-striped arms around a smiley core, stars twinkling
|
||||
// both arms match, so half a turn per loop is seamless; the dark sky gets a white rim for dark backgrounds
|
||||
const{sin,cos,PI,exp,max,min,hypot}=Math,T=2*PI
|
||||
export const frames=20,delay=90
|
||||
const SKY='#2b3a7a',ARM='#9775fa',STRIPE='#faa2c1',BL='#ff8787',SQ=.64,M=9.4
|
||||
const spk=(c,x,y,s)=>{c.lineWidth=3;c.fillStyle='#fff';c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.2,-s*.2],[0,s,s*.2,s*.2],[-s,0,-s*.2,s*.2],[0,-s,-s*.2,-s*.2]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const disc=()=>{c.beginPath();c.arc(128,128,112,0,T)},ph=-t*PI
|
||||
disc();c.lineWidth=18;c.strokeStyle='#fff';c.stroke();c.fillStyle=SKY;c.fill();c.strokeStyle='#111'
|
||||
c.save();disc();c.clip()
|
||||
for(const[x,y,o]of[[44,62,0],[206,50,.3],[218,190,.6],[50,198,.15],[128,30,.8],[136,230,.45]])spk(c,x,y,2+4*max(0,sin((t+o)*2*T)))
|
||||
const P=(th,k)=>{const r=16*exp(.19*th),q=th+k*PI+ph;return[128+r*cos(q),128+r*sin(q)*SQ]}
|
||||
for(const k of[0,1]){
|
||||
const C=[];for(let th=0;th<=M;th+=.2)C.push([P(th,k),th])
|
||||
const side=(f,g)=>C.map(([[x,y],th],j)=>{const[[x0,y0]]=C[max(0,j-1)],[[x1,y1]]=C[min(C.length-1,j+1)],l=hypot(x1-x0,y1-y0),w=f*(24*(1-th/M)+2);return[x-(y1-y0)/l*w*g,y+(x1-x0)/l*w*g]})
|
||||
for(const[f,col,lw]of[[1,ARM,5],[.4,STRIPE,0]]){c.beginPath();for(const[x,y]of[...side(f,1),...side(f,-1).reverse()])c.lineTo(x,y);c.closePath();c.fillStyle=col;c.fill();if(lw)c.lineWidth=lw,c.stroke()}
|
||||
c.fillStyle='#fff';for(const th of[3.4,5.2,7,8.4]){const[x,y]=P(th,k);c.beginPath();c.arc(x,y,2.6,0,T);c.fill()}
|
||||
}
|
||||
c.lineWidth=5;c.fillStyle='#fff3bf';c.beginPath();c.ellipse(128,128,36,28,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#ffd43b';c.beginPath();c.ellipse(128,128,26,20,0,0,T);c.fill();c.lineWidth=4;c.stroke()
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(128+d*9,127,4.5,PI*1.15,PI*1.85),c.stroke()
|
||||
c.lineWidth=3.5;c.beginPath();c.arc(128,130,5,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*16,133,4,2.5,0,0,T),c.fill()
|
||||
c.restore();c.lineWidth=7;disc();c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// giraffe stretching its long neck up to a branch, munching leaves with its jaw working and an ear flicking
|
||||
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const GY='#ffc078',SP='#a9744f',MZ='#ffe8cc',BR='#8d6346',LF='#69db7c',LD='#51cf66',BL='#ffa8a8'
|
||||
export default(c,t,i)=>{
|
||||
const ch=abs(sin(3*PI*t)),hx=-3*ch,fl=i==10||i==11?.7:i==9||i==12?.35:0
|
||||
const D=(wd,col,f)=>{for(const[l,s]of[[wd,'#111'],[wd-10,col]])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
D(20,BR,()=>{c.moveTo(118,24);c.quadraticCurveTo(190,18,248,38)})
|
||||
c.fillStyle=LF;for(const[x,y,r]of[[150,34,.6],[176,40,.2],[236,52,-.4],[244,26,-1]])c.beginPath(),c.ellipse(x,y,14,8,r,0,T),c.fill(),c.stroke()
|
||||
for(const[x,y]of[[54,196],[104,198]])D(18,GY,()=>{c.moveTo(x,y);c.lineTo(x-2,236)})
|
||||
for(const[x,y]of[[70,198],[120,196]])D(18,GY,()=>{c.moveTo(x,y);c.lineTo(x+2,238)})
|
||||
c.fillStyle=BR;for(const x of[52,72,102,122])c.beginPath(),c.roundRect(x-10,232,20,12,4),c.fill(),c.stroke()
|
||||
D(10,GY,()=>{c.moveTo(42,170);c.quadraticCurveTo(26,184,30,206)})
|
||||
c.fillStyle=BR;c.beginPath();c.ellipse(30,210,6,10,0,0,T);c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
for(const x of[188,200])D(10,GY,()=>{c.moveTo(x+hx,70);c.lineTo(x+hx-2,48)})
|
||||
c.fillStyle=BR;for(const x of[186,198])c.beginPath(),c.arc(x+hx,46,7,0,T),c.fill(),c.stroke()
|
||||
D(16,BR,()=>{for(let k=0;k<=8;k++){const u=k/8,o=k%2?-7:0;c.lineTo(96+u*(70+hx)+o,158-u*86+o)}})
|
||||
const sil=()=>{c.beginPath();c.ellipse(86,180,50,28,-.08,0,T);c.moveTo(102,164);c.lineTo(174+hx,80);c.lineTo(196+hx,94);c.lineTo(130,176);c.closePath();c.moveTo(220+hx,80);c.ellipse(194+hx,80,27,18,-.35,0,T)}
|
||||
sil();c.lineWidth=14;c.stroke();c.fillStyle=GY;sil();c.fill()
|
||||
c.save();sil();c.clip();c.fillStyle=SP
|
||||
for(const[x,y,r]of[[60,172,11],[86,186,12],[112,170,10],[78,160,8],[46,190,7],[122,190,8],[118,148,9],[136,128,9],[150,108,8],[132,150,6],[164,96,6]])c.beginPath(),c.ellipse(x,y,r,r*.8,.5,0,T),c.fill()
|
||||
c.restore();c.lineWidth=7
|
||||
c.save();c.translate(178+hx,70);c.rotate(-.9-fl);c.fillStyle=GY;c.beginPath();c.ellipse(-12,0,14,7,0,0,T);c.fill();c.stroke();c.fillStyle=BL;c.beginPath();c.ellipse(-12,0,7,3,0,0,T);c.fill();c.restore()
|
||||
c.save();c.translate(212+hx,74);c.rotate(-.35)
|
||||
c.fillStyle=MZ;c.beginPath();c.ellipse(4,-2,13,11,0,0,T);c.fill();c.lineWidth=5;c.stroke()
|
||||
c.beginPath();c.moveTo(8,8+ch*2);c.quadraticCurveTo(0,12+ch*5,-8,8);c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(8,-4,2.5,2,0,0,T);c.fill()
|
||||
c.restore()
|
||||
D(10,LD,()=>{c.moveTo(224+hx,82+ch*2);c.quadraticCurveTo(232,70,236,56)})
|
||||
c.fillStyle=LF;c.beginPath();c.ellipse(232+hx*.5,84+ch*3,10,6,.5+ch*.3,0,T);c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
c.lineWidth=5;c.beginPath();c.arc(190+hx,76,6,1.1*PI,1.9*PI);c.stroke();c.lineWidth=7
|
||||
c.fillStyle=BL;c.beginPath();c.ellipse(196+hx,88,7,4,-.3,0,T);c.fill()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// cute helicopter hovering and gently tilting, main rotor whirring, tail rotor spinning, downwash puffs below
|
||||
const{sin,cos,PI,abs,round}=Math,T=2*PI
|
||||
export const frames=16,delay=70
|
||||
const B='#ff6b6b',BD='#e03131',GL='#a5d8ff',SK='#868e96',RT='#dee2e6',BL='#ffa8a8'
|
||||
const body=c=>{c.beginPath();c.ellipse(140,138,62,44,0,0,T)}
|
||||
export default(c,t)=>{
|
||||
const b=round(4*sin(t*T)),r=.05*sin(t*T+1),th=t*T*2
|
||||
c.lineWidth=5
|
||||
for(const d of[-1,1])for(let k=0;k<2;k++){const p=(t*2+k/2)%1,x=140+d*(30+64*p),y=226+8*p,l=12*sin(PI*p);if(l>2)for(const[w,s]of[[9,'#111'],[3,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x-d*l,y-l*.3),c.lineTo(x+d*l,y+l*.3),c.stroke()}
|
||||
c.strokeStyle='#111'
|
||||
c.save();c.translate(140,140+b);c.rotate(r);c.translate(-140,-140)
|
||||
for(const[lw,st]of[[12,'#111'],[5,SK]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.moveTo(118,176),c.lineTo(112,204),c.moveTo(162,176),c.lineTo(168,204),c.moveTo(80,204),c.lineTo(196,204),c.quadraticCurveTo(212,204,214,192),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle=B;c.beginPath();c.moveTo(92,122);c.lineTo(34,112);c.lineTo(34,128);c.lineTo(92,152);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=BD;c.beginPath();c.moveTo(28,126);c.lineTo(18,90);c.lineTo(38,94);c.lineTo(44,120);c.closePath();c.fill();c.stroke()
|
||||
const tp=t*T*6
|
||||
for(const a of[tp,tp+PI/2])for(const[lw,st]of[[10,'#111'],[4,RT]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.moveTo(26-14*cos(a),104-14*sin(a)),c.lineTo(26+14*cos(a),104+14*sin(a)),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=SK;c.beginPath();c.arc(26,104,5,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=SK;c.beginPath();c.roundRect(132,80,16,18,4);c.fill();c.stroke()
|
||||
body(c);c.fillStyle=B;c.fill()
|
||||
c.save();body(c);c.clip();c.fillStyle=BD;c.fillRect(70,160,140,30)
|
||||
c.fillStyle=GL;c.beginPath();c.ellipse(170,124,40,30,0,0,T);c.fill();c.lineWidth=5;c.stroke();c.restore()
|
||||
c.lineWidth=7;body(c);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.arc(170,124,26,PI*1.1,PI*1.4);c.stroke();c.strokeStyle='#111'
|
||||
c.fillStyle='#111';for(const x of[156,182])c.beginPath(),c.ellipse(x,124,5,7,0,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[154,180])c.beginPath(),c.arc(x,121,2.5,0,T),c.fill()
|
||||
c.fillStyle=BL;for(const x of[142,196])c.beginPath(),c.ellipse(x,150,8,5,0,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(169,146,7,.2*PI,.8*PI);c.stroke()
|
||||
for(const[lw,st]of[[9,'#111'],[3,RT]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.ellipse(140,78,104,7,0,0,T),c.stroke()
|
||||
for(const a of[th,th+PI/2])for(const[lw,st]of[[11,'#111'],[5,SK]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.moveTo(140-100*cos(a),78-5*sin(a)),c.lineTo(140+100*cos(a),78+5*sin(a)),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=SK;c.beginPath();c.arc(140,78,8,0,T);c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// striped hot-air balloon with a happy face bobbing up and down, burner flame puffing, little clouds drifting by
|
||||
const{sin,PI,round}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const ST=['#ff6b6b','#ffd43b','#4dabf7','#fff'],SK='#fa5252',BK='#a9744f',BKD='#7f5539',FO='#ff922b',FY='#ffd43b',BL='#ffa8a8'
|
||||
const env=c=>{c.beginPath();c.moveTo(100,170);c.bezierCurveTo(30,128,36,16,128,16);c.bezierCurveTo(220,16,226,128,156,170);c.closePath()}
|
||||
// union outline: stroke every puff wide in black, then fill them all white
|
||||
const cloud=(c,x,y)=>{const b=[[-16,4,12],[2,-4,16],[20,4,11]];c.lineWidth=14;for(const[a,d,r]of b)c.beginPath(),c.arc(x+a,y+d,r,0,T),c.stroke();c.fillStyle='#fff';for(const[a,d,r]of b)c.beginPath(),c.arc(x+a,y+d,r,0,T),c.fill();c.lineWidth=7}
|
||||
export default(c,t)=>{
|
||||
const b=round(6*sin(t*T)),p=.5+.5*sin(4*T*t),fh=12+14*p
|
||||
cloud(c,round(48+8*sin(t*T)),212);cloud(c,round(204-8*sin(t*T+1)),56)
|
||||
c.translate(0,b)
|
||||
for(const[w,s]of[[9,'#111'],[3,'#ffd8a8']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(106,180),c.lineTo(112,206),c.moveTo(150,180),c.lineTo(144,206),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
c.fillStyle=FO;c.lineWidth=5;c.beginPath();c.moveTo(118,204);c.quadraticCurveTo(114,196-fh*.4,128,196-fh);c.quadraticCurveTo(142,196-fh*.4,138,204);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=FY;c.beginPath();c.moveTo(123,203);c.quadraticCurveTo(121,199-fh*.3,128,199-fh*.6);c.quadraticCurveTo(135,199-fh*.3,133,203);c.closePath();c.fill()
|
||||
c.lineWidth=7;env(c);c.fillStyle=ST[0];c.fill()
|
||||
c.save();env(c);c.clip()
|
||||
for(const[k,rx]of[[1,70],[2,46],[3,20]])c.fillStyle=ST[k],c.beginPath(),c.ellipse(128,92,rx,120,0,0,T),c.fill()
|
||||
c.lineWidth=4;for(const rx of[70,46,20])c.beginPath(),c.ellipse(128,92,rx,120,0,0,T),c.stroke()
|
||||
c.restore()
|
||||
c.lineWidth=7;env(c);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=6;c.beginPath();c.arc(128,96,62,PI*1.12,PI*1.3);c.stroke();c.strokeStyle='#111'
|
||||
c.fillStyle='#111';for(const x of[108,148])c.beginPath(),c.ellipse(x,108,6,8,0,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const x of[106,146])c.beginPath(),c.arc(x,105,2.5,0,T),c.fill()
|
||||
c.fillStyle=BL;for(const x of[92,164])c.beginPath(),c.ellipse(x,124,9,5,0,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128,118,10,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=SK;c.beginPath();c.moveTo(100,170);c.lineTo(156,170);c.lineTo(150,184);c.lineTo(106,184);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=BKD;c.beginPath();c.roundRect(102,200,52,10,5);c.fill();c.stroke()
|
||||
c.fillStyle=BK;c.beginPath();c.roundRect(106,208,44,30,6);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();for(const y of[218,228])c.moveTo(108,y),c.lineTo(148,y);for(const x of[120,136])c.moveTo(x,210),c.lineTo(x,236);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// tiny smiling island with a palm tree swaying in the breeze, waves lapping all around it, coconuts in the fronds
|
||||
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||
export const frames=12,delay=120
|
||||
const SEA='#4dabf7',SL='#a5d8ff',SAND='#ffd8a8',SD='#ffc078',TR='#a9744f',TD='#7f5539',FR='#51cf66',FD='#2f9e44',CO='#8d6346',BL='#ff8787'
|
||||
export default(c,t)=>{
|
||||
const a=t*T,s=sin(a),f=4*sin(2*a)
|
||||
c.beginPath();for(let k=0;k<=96;k++){const q=k/96*T,r=1+.03*sin(8*q-2*a);c.lineTo(128+114*r*cos(q),198+42*r*sin(q))}c.closePath();c.fillStyle=SEA;c.fill();c.stroke()
|
||||
c.strokeStyle=SL;c.lineWidth=5;c.beginPath();c.ellipse(128,198,90+f,31+f*.4,0,0,T);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=5;c.beginPath();c.ellipse(128,194,74+f*.7,26+f*.3,0,0,T);c.stroke()
|
||||
for(const[x,y,o]of[[38,204,0],[214,196,2],[96,228,4],[170,226,1]]){const b=2*sin(2*a+o);c.lineWidth=4;c.beginPath();c.arc(x,y+b,7,PI*1.1,PI*1.9);c.stroke();c.beginPath();c.arc(x+13,y+b,7,PI*1.1,PI*1.9);c.stroke()}
|
||||
c.strokeStyle='#111';c.lineWidth=7;c.fillStyle=SAND;c.beginPath();c.ellipse(128,190,64,22,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=SD;c.beginPath();c.ellipse(96,194,14,4,0,0,T);c.fill()
|
||||
const px=150+10*s,py=84,bx=116,by=186,cx=110,cy=132
|
||||
for(const[w,col]of[[26,'#111'],[16,TR]])c.lineWidth=w,c.strokeStyle=col,c.beginPath(),c.moveTo(bx,by),c.quadraticCurveTo(cx,cy,px,py),c.stroke()
|
||||
c.strokeStyle=TD;c.lineWidth=3
|
||||
for(let u=.12;u<.9;u+=.13){const v=1-u,x=v*v*bx+2*u*v*cx+u*u*px,y=v*v*by+2*u*v*cy+u*u*py,tx=2*v*(cx-bx)+2*u*(px-cx),ty=2*v*(cy-by)+2*u*(py-cy),l=Math.hypot(tx,ty),nx=-ty/l,ny=tx/l;c.beginPath();c.moveTo(x-nx*6,y-ny*6);c.quadraticCurveTo(x+tx/l*3,y+ty/l*3,x+nx*6,y+ny*6);c.stroke()}
|
||||
c.strokeStyle='#111'
|
||||
const frond=(d,q,L,k)=>{c.save();c.translate(px,py);c.scale(d,1);c.rotate(q+.1*sin(a+k*.7));c.fillStyle=FR;c.lineWidth=6;c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(L*.5,-20,L,10);c.quadraticCurveTo(L*.5,4,0,0);c.fill();c.stroke();c.strokeStyle=FD;c.lineWidth=3;c.beginPath();c.moveTo(4,-2);c.quadraticCurveTo(L*.5,-10,L-6,8);c.stroke();c.restore();c.strokeStyle='#111'}
|
||||
for(const[d,q,L,k]of[[-1,-.7,58,0],[1,-.75,56,1],[-1,.05,66,2],[1,.05,68,3],[-1,.62,52,4],[1,.6,54,5]])frond(d,q,L,k)
|
||||
c.fillStyle=CO;c.lineWidth=5;for(const[x,y]of[[-9,10],[7,11],[-1,19]])c.beginPath(),c.arc(px+x,py+y,9,0,T),c.fill(),c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(146+d*12,196,4,0,T),c.fill()
|
||||
c.lineWidth=3.5;c.beginPath();c.arc(146,200,6,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(146+d*22,202,5,3,0,0,T),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// latte in a teal cup seen from above at an angle, a heart of foam blooming in the coffee and fading, steam curling up
|
||||
const{sin,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=80
|
||||
const CU='#38d9a9',CD='#0ca678',SA='#fff',CO='#a9744f',CR='#c99a6e',FO='#fff4e6',BL='#ffa8a8'
|
||||
const heart=(c,s)=>{c.beginPath();c.moveTo(0,s*.95);c.bezierCurveTo(-s*1.5,0,-s*.9,-s*1.05,0,-s*.45);c.bezierCurveTo(s*.9,-s*1.05,s*1.5,0,0,s*.95);c.closePath()}
|
||||
export default(c,t)=>{
|
||||
c.fillStyle=SA;c.beginPath();c.ellipse(128,204,112,34,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(128,200,74,20,0,0,T);c.stroke();c.lineWidth=7
|
||||
for(const[w,s]of[[22,'#111'],[11,CU]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.ellipse(208,146,22,17,-.2,-1.2,1.6),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle=CU;c.beginPath();c.moveTo(52,110);c.bezierCurveTo(56,230,200,230,204,110);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24,174,6,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*24-2,172,2.2,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(128,180,8,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*44,184,9,5,0,0,T),c.fill()
|
||||
c.lineWidth=7;c.fillStyle=CU;c.beginPath();c.ellipse(128,110,76,40,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=CO;c.beginPath();c.ellipse(128,112,62,31,0,0,T);c.fill();c.lineWidth=5;c.stroke()
|
||||
c.fillStyle=CR;c.beginPath();c.ellipse(128,113,50,23,0,0,T);c.fill()
|
||||
const p=t,g=min(1,p/.3),m=min(1,max(0,(p-.25)/.25)),f=p>.82?1-(p-.82)/.18:1
|
||||
if(p>.02){
|
||||
c.save();c.globalAlpha=f;c.translate(128,114);c.scale(1+.25*(1-f),.52*(1+.25*(1-f)));c.fillStyle=FO
|
||||
const rc=22*g*(1-m);if(rc>.5)c.beginPath(),c.arc(0,4,rc,0,T),c.fill()
|
||||
if(m>0){heart(c,30*m);c.fill();c.strokeStyle=CR;c.lineWidth=5;heart(c,17*m);c.stroke();c.fillStyle=FO;heart(c,11*m);c.fill()}
|
||||
c.restore();c.strokeStyle='#111'
|
||||
}
|
||||
c.lineCap='round'
|
||||
for(let k=0;k<3;k++){
|
||||
const x0=102+k*26,pts=[];for(let s=0;s<=1.001;s+=.1)pts.push([x0+7*sin(T*(s*1.1-t)+k*2),64-44*s])
|
||||
for(const[w,s]of[[9,'#111'],[4,'#fff']]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();pts.forEach(([x,y])=>c.lineTo(x,y));c.stroke()}
|
||||
}
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// lava lamp with a happy base, pink blobs rising, merging and sinking through blue goo
|
||||
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||
export const frames=24,delay=90
|
||||
const CAP='#9775fa',CD='#7048e8',GOO='#74c0fc',BLOB='#f783ac',BH='#ffdeeb',BL='#faa2c1'
|
||||
const glass=c=>{c.beginPath();c.moveTo(100,62);c.lineTo(156,62);c.lineTo(180,166);c.quadraticCurveTo(184,190,160,190);c.lineTo(96,190);c.quadraticCurveTo(72,190,76,166);c.closePath()}
|
||||
export default(c,t)=>{
|
||||
c.fillStyle=CAP;c.beginPath();c.moveTo(94,186);c.lineTo(162,186);c.lineTo(194,232);c.quadraticCurveTo(198,244,184,244);c.lineTo(72,244);c.quadraticCurveTo(58,244,62,232);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=CD;c.beginPath();c.roundRect(86,182,84,12,6);c.fill();c.lineWidth=5;c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*18,214,5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(126+d*18,212,1.8,0,T),c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(128,219,7,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*34,224,8,4,0,0,T),c.fill()
|
||||
c.lineWidth=7;glass(c);c.fillStyle=GOO;c.fill()
|
||||
c.save();glass(c);c.clip()
|
||||
const bl=[[0,124,20],[.3,110,16],[.55,146,14],[.8,132,11]].map(([p,x,r])=>{
|
||||
const s=sin(T*(t+p)),y=126+54*cos(T*(t+p)),v=abs(s)
|
||||
return[x+7*sin(2*T*(t+p)),y,r*(1-.12*v),r*(1+.3*v)]
|
||||
})
|
||||
const blobs=()=>{c.beginPath();c.ellipse(128,198,58,20,0,0,T);c.moveTo(158,58);c.ellipse(128,58,30,9,0,0,T);for(const[x,y,rx,ry]of bl)c.moveTo(x+rx,y),c.ellipse(x,y,rx,ry,0,0,T)}
|
||||
c.lineWidth=10;blobs();c.stroke();c.fillStyle=BLOB;blobs();c.fill()
|
||||
c.fillStyle=BH;for(const[x,y,rx,ry]of bl)c.beginPath(),c.ellipse(x-rx*.35,y-ry*.4,rx*.28,ry*.2,-.5,0,T),c.fill()
|
||||
c.restore()
|
||||
c.lineWidth=7;glass(c);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=6;c.beginPath();c.moveTo(108,78);c.lineTo(92,150);c.stroke();c.strokeStyle='#111'
|
||||
c.lineWidth=7;c.fillStyle=CAP;c.beginPath();c.moveTo(96,64);c.lineTo(160,64);c.lineTo(146,22);c.quadraticCurveTo(144,16,138,16);c.lineTo(118,16);c.quadraticCurveTo(112,16,110,22);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=CD;c.beginPath();c.roundRect(92,58,72,10,5);c.fill();c.lineWidth=5;c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// pink lotus on a lily pad opening into full bloom and closing back to a bud, ripples spreading on the pond
|
||||
const{sin,cos,PI,max,min}=Math,T=2*PI
|
||||
export const frames=16,delay=100
|
||||
const W='#74c0fc',WL='#d0ebff',PAD='#51cf66',PD='#2f9e44',P1='#fcc2d7',P2='#f783ac',PV='#fff0f6',POD='#ffd43b',PDK='#f59f00'
|
||||
const spk=(c,x,y,s)=>{c.lineWidth=3;c.fillStyle='#fff';c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.2,-s*.2],[0,s,s*.2,s*.2],[-s,0,-s*.2,s*.2],[0,-s,-s*.2,-s*.2]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const o=min(1,max(0,(1-cos(t*T))/2*1.3-.12)),bx=128,by=166
|
||||
const pond=()=>{c.beginPath();c.ellipse(128,174,118,48,0,0,T)}
|
||||
pond();c.fillStyle=W;c.fill();c.stroke()
|
||||
c.save();pond();c.clip()
|
||||
for(let k=0;k<2;k++){const p=(t*2+k/2)%1,r=98+50*p;c.strokeStyle=WL;c.lineWidth=5*(1-p)+1;c.beginPath();c.ellipse(128,176,r,r*.36,0,0,T);c.stroke()}
|
||||
c.restore();c.strokeStyle='#111';c.lineWidth=5
|
||||
c.fillStyle=PAD;c.beginPath();c.ellipse(204,204,16,6,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.moveTo(128,176);c.ellipse(128,176,96,32,0,.4,.4+T-.45);c.closePath();c.fill();c.stroke()
|
||||
c.strokeStyle=PD;c.lineWidth=3;for(const q of[1.2,1.9,2.6,3.4,4.2,5,5.7])c.beginPath(),c.moveTo(128,176),c.lineTo(128+82*cos(q),176+26*sin(q)),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
const petal=(a,L,w,col)=>{c.save();c.translate(bx,by);c.rotate(a);c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(-w,-L*.5,0,-L);c.quadraticCurveTo(w,-L*.5,0,0);c.fillStyle=col;c.fill();c.lineWidth=7;c.stroke();c.strokeStyle=PV;c.lineWidth=4;c.beginPath();c.moveTo(0,-12);c.lineTo(0,-L*.68);c.stroke();c.restore();c.strokeStyle='#111'}
|
||||
petal(0,117,55,P1);for(const d of[-1,1])petal(d*(.36+.95*o),107,55,P1)
|
||||
c.fillStyle=POD;c.lineWidth=6;c.beginPath();c.ellipse(128,109,26,12,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=PDK;for(const x of[-13,0,13])c.beginPath(),c.arc(128+x,109,3,0,T),c.fill()
|
||||
for(const d of[-1,1])petal(d*(.12+.72*o),96,49,P2)
|
||||
petal(0,88*(1-.52*o),49,P2)
|
||||
if(o>.7)for(const[x,y,q]of[[46,62,0],[210,54,.5]])spk(c,x,y,(o-.7)/.3*(5+5*max(0,sin((t+q)*4*T))))
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
// maneki-neko lucky cat beckoning with its raised paw, hugging a gold koban coin, collar bell swinging
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const W='#fff',OR='#ffa94d',DK='#495057',PK='#faa2c1',CO='#ff6b6b',G='#ffd43b',GD='#fab005',CU='#f783ac',CUD='#e64980'
|
||||
export default(c,t)=>{
|
||||
// the paw curls down twice per loop: its height squashes by cos of the curl and the toe beans tip out of view
|
||||
const cu=.5-.5*cos(2*T*t),k=cos(cu*1.2),bell=.35*sin(2*T*t-.8)
|
||||
c.fillStyle=CU;c.beginPath();c.roundRect(34,206,188,36,16);c.fill();c.stroke()
|
||||
c.fillStyle=CUD;for(const x of[44,212])c.beginPath(),c.arc(x,238,7,0,T),c.fill(),c.stroke()
|
||||
c.fillStyle=W;c.beginPath();c.ellipse(128,176,64,50,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=OR;c.save();c.beginPath();c.ellipse(128,176,64,50,0,0,T);c.clip();c.beginPath();c.ellipse(78,206,30,26,0,0,T);c.fill();c.restore()
|
||||
c.beginPath();c.ellipse(128,176,64,50,0,0,T);c.stroke()
|
||||
c.fillStyle=W;for(const x of[100,156])c.beginPath(),c.ellipse(x,220,18,10,0,0,T),c.fill(),c.stroke()
|
||||
c.fillStyle=W;c.beginPath();c.moveTo(78,74);c.lineTo(84,30);c.lineTo(114,58);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=DK;c.beginPath();c.moveTo(142,58);c.lineTo(172,30);c.lineTo(178,74);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=PK;c.lineWidth=4;c.beginPath();c.moveTo(88,60);c.lineTo(89,42);c.lineTo(104,56);c.closePath();c.fill()
|
||||
c.lineWidth=7;c.fillStyle=W;c.beginPath();c.ellipse(128,100,64,52,0,0,T);c.fill()
|
||||
c.save();c.clip();c.fillStyle=OR;c.beginPath();c.ellipse(82,66,34,26,.3,0,T);c.fill();c.fillStyle=DK;c.beginPath();c.ellipse(170,60,22,16,-.3,0,T);c.fill();c.restore()
|
||||
c.beginPath();c.ellipse(128,100,64,52,0,0,T);c.stroke()
|
||||
c.lineWidth=5;for(const x of[104,152])c.beginPath(),c.arc(x,104,10,PI*1.15,PI*1.85),c.stroke()
|
||||
c.fillStyle=PK;for(const x of[90,166])c.beginPath(),c.ellipse(x,118,9,5,0,0,T),c.fill()
|
||||
c.fillStyle=CUD;c.lineWidth=3;c.beginPath();c.moveTo(123,112);c.lineTo(133,112);c.lineTo(128,118);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.arc(122,120,6,.1*PI,.9*PI);c.arc(134,120,6,.1*PI,.9*PI);c.stroke()
|
||||
for(const d of[-1,1])for(const[dy,ang]of[[-4,-.12],[6,.12]])for(const[w,s]of[[7,'#111'],[2,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(128+d*48,116+dy),c.lineTo(128+d*78,116+dy+ang*30),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
c.lineWidth=6;c.fillStyle=CO;c.beginPath();c.roundRect(84,144,88,14,7);c.fill();c.stroke()
|
||||
c.save();c.translate(128,156);c.rotate(bell)
|
||||
c.fillStyle=G;c.lineWidth=5;c.beginPath();c.arc(0,12,11,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=3;c.beginPath();c.moveTo(-10,10);c.lineTo(10,10);c.moveTo(0,14);c.lineTo(0,22);c.stroke();c.beginPath();c.arc(0,16,2.5,0,T);c.fillStyle='#111';c.fill()
|
||||
c.restore()
|
||||
c.lineWidth=6;c.fillStyle=G;c.beginPath();c.ellipse(96,188,20,30,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=GD;c.beginPath();c.ellipse(96,188,13,22,0,0,T);c.fill()
|
||||
c.lineWidth=3;c.beginPath();for(const y of[176,184,192,200])c.moveTo(88,y),c.lineTo(104,y);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=3;c.beginPath();c.arc(96,188,16,PI*1.15,PI*1.45);c.stroke();c.strokeStyle='#111'
|
||||
c.lineWidth=6;c.fillStyle=W;c.beginPath();c.ellipse(108,176,14,12,.3,0,T);c.fill();c.stroke()
|
||||
for(const[w,s]of[[30,'#111'],[18,W]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(170,166),c.quadraticCurveTo(192,150,194,108),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=6
|
||||
const py=96-14*k
|
||||
c.fillStyle=W;c.beginPath();c.ellipse(194,py+14*(1-k)*.4,18,18*max(.45,k),0,0,T);c.fill();c.stroke()
|
||||
if(k>.5){c.fillStyle=PK;c.beginPath();c.ellipse(194,py+4,7,6*k,0,0,T);c.fill();for(const d of[-9,0,9])c.beginPath(),c.ellipse(194+d,py-9*k,3.5,3.5*k,0,0,T),c.fill()}
|
||||
else{c.lineWidth=4;c.beginPath();for(const d of[-6,6])c.moveTo(194+d,py+4),c.lineTo(194+d,py+12);c.stroke()}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
// big smiley maple leaf rocking side to side like a pendulum as it floats, two little leaves fluttering down beside it
|
||||
const{sin,cos,PI,abs,min}=Math,T=2*PI
|
||||
export const frames=20,delay=90
|
||||
const LEAF=[[0,-1],[.16,-.58],[.42,-.74],[.36,-.36],[.84,-.48],[.6,-.1],[.76,.08],[.4,.14],[.52,.42],[.12,.28],[0,.44]]
|
||||
const PTS=[...LEAF,...LEAF.slice(0,-1).reverse().map(([x,y])=>[-x,y])],TIPS=[[0,-1],[.42,-.74],[.84,-.48],[.76,.08],[.52,.42]]
|
||||
const CL=[['#ff6b6b','#c92a2a'],['#ff922b','#d9480f'],['#ffd43b','#e67700'],['#fa5252','#a61e1e']]
|
||||
const leaf=(c,x,y,S,rot,fx,[col,dk],lw,v0=0)=>{
|
||||
const m=([px,py])=>{const X=px*S*fx,Y=py*S;return[x+X*cos(rot)-Y*sin(rot),y+X*sin(rot)+Y*cos(rot)]}
|
||||
for(const[w,s]of[[lw*1.8,'#111'],[lw*.7,dk]]){const[a,b]=m([0,.4]),[e,f]=m([0,.95]);c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.moveTo(a,b);c.lineTo(e,f);c.stroke()}
|
||||
c.strokeStyle='#111';c.beginPath();for(const p of PTS)c.lineTo(...m(p));c.closePath();c.fillStyle=col;c.fill();c.lineWidth=lw;c.stroke()
|
||||
c.strokeStyle=dk;c.lineWidth=lw*.5;const[ox,oy]=m([0,.3])
|
||||
for(const[tx,ty]of TIPS)for(const d of tx?[-1,1]:[1]){const[ex,ey]=m([tx*d*.62,ty*.62]),[sx,sy]=v0?m([tx*d*v0,ty*v0]):[ox,oy];c.beginPath();c.moveTo(sx,sy);c.lineTo(ex,ey);c.stroke()}
|
||||
c.strokeStyle='#111';return m
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const a=t*T,s=sin(a),x=128+38*s,y=126-16*s*s,rot=-.4*s
|
||||
for(const[o,x0,k]of[[0,40,1],[.5,214,2]]){
|
||||
const p=(t+o)%1,S=24*min(1,sin(PI*p)*2.5)
|
||||
if(S>2)leaf(c,x0+12*sin(p*T*2),34+p*188,S,.4*sin(p*T*2+o*6),cos(p*T*2+o*3),CL[k],4)
|
||||
}
|
||||
const v=cos(a),d=v>0?1:-1
|
||||
if(abs(v)>.5)for(const[dy,l]of[[-18,22],[6,30],[30,18]])for(const[w,st]of[[9,'#111'],[3.5,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(x-d*68,y+dy),c.lineTo(x-d*(68+l*abs(v)),y+dy),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
const m=leaf(c,x,y,68,rot,1,CL[0],7,.38),lk=v*.03
|
||||
for(const d of[-1,1]){
|
||||
const[ex,ey]=m([d*.2,-.18]);c.fillStyle='#111';c.beginPath();c.ellipse(ex,ey,5.5,7,rot,0,T);c.fill()
|
||||
const[hx,hy]=m([d*.2-.03+lk,-.23]);c.fillStyle='#fff';c.beginPath();c.arc(hx,hy,2.2,0,T);c.fill()
|
||||
const[bx,by]=m([d*.38,-.04]);c.fillStyle='#ffa8a8';c.beginPath();c.ellipse(bx,by,7,4,rot,0,T);c.fill()
|
||||
}
|
||||
const[a0,b0]=m([-.13,-.04]),[a1,b1]=m([0,.1]),[a2,b2]=m([.13,-.04]);c.lineWidth=4;c.beginPath();c.moveTo(a0,b0);c.quadraticCurveTo(a1,b1,a2,b2);c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
// neon smiley heart sign on a dark board, glowing pink then flickering off and on with a little buzz
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const BOARD='#343a40',SCREW='#5c636a',PK='#f783ac',PL='#fff0f6',OFF='#7a3352',WIRE='#ced4da',ZAP='#ffd43b'
|
||||
const ON=[1,1,1,1,1,1,1,1,1,1,0,1,0,0,1,1,1,1,1,1,1,1,0,1]
|
||||
const heart=c=>{c.beginPath();c.moveTo(128,196);c.bezierCurveTo(42,140,62,58,128,100);c.bezierCurveTo(194,58,214,140,128,196)}
|
||||
const face=c=>{c.beginPath();for(const x of[110,146])c.moveTo(x,122),c.lineTo(x,132);c.moveTo(112,146);c.quadraticCurveTo(128,160,144,146)}
|
||||
export default(c,t,i)=>{
|
||||
const on=ON[i],zap=ON[i]!=ON[(i+23)%24]
|
||||
for(const[x0,x1]of[[58,74],[198,182]])for(const[w,st]of[[11,'#111'],[4,WIRE]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(x0,2),c.lineTo(x1,46),c.stroke()
|
||||
const board=()=>{c.beginPath();c.roundRect(22,42,212,190,22)}
|
||||
c.lineWidth=18;c.strokeStyle='#fff';board();c.stroke()
|
||||
c.fillStyle=BOARD;board();c.fill();c.lineWidth=7;c.strokeStyle='#111';c.stroke()
|
||||
c.fillStyle=SCREW;for(const[x,y]of[[40,60],[216,60],[40,214],[216,214]])c.beginPath(),c.arc(x,y,5,0,T),c.fill()
|
||||
if(on){
|
||||
c.save();board();c.clip();c.globalAlpha=.16;c.fillStyle=PK;c.beginPath();c.ellipse(128,140,100,82,0,0,T);c.fill()
|
||||
c.strokeStyle=PK;for(const[w,al]of[[30,.22],[19,.4]]){c.globalAlpha=al;c.lineWidth=w;heart(c);c.stroke();face(c);c.stroke()}
|
||||
c.restore()
|
||||
}
|
||||
c.strokeStyle='#111';c.lineWidth=13;heart(c);c.stroke();face(c);c.stroke()
|
||||
c.strokeStyle=on?PK:OFF;c.lineWidth=7;heart(c);c.stroke();face(c);c.stroke()
|
||||
if(on){c.strokeStyle=PL;c.lineWidth=2.5;heart(c);c.stroke();face(c);c.stroke()}
|
||||
c.strokeStyle='#111'
|
||||
if(zap)for(const[x,y,d]of[[190,84,1],[66,84,-1]])for(const[w,st]of[[9,'#111'],[3.5,ZAP]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(x,y),c.lineTo(x+d*8,y-6),c.lineTo(x+d*4,y-12),c.lineTo(x+d*14,y-20),c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// otter floating on its back, banging a clam on the stone on its tummy while it bobs on the waves
|
||||
const{sin,cos,PI,abs,max}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const BR='#a9744f',BD='#8d6346',BE='#ffd8a8',WA='#4dabf7',WL='#a5d8ff',ST='#ced4da',SD='#868e96',CL='#faa2c1',CD='#f06595',BL='#ffa8a8'
|
||||
export default(c,t)=>{
|
||||
const b=Math.round(4*sin(T*t)),r=.05*sin(T*t+.6),h=max(0,(abs(sin(T*t))-.4)/.6),bang=h==0
|
||||
const wy=(x,o=0)=>186+5*sin(x/20-T*t+o)
|
||||
const sea=(o,dy)=>{c.fillStyle=WA;c.beginPath();c.moveTo(22,244);c.quadraticCurveTo(8,244,8,230);for(let x=8;x<=248;x+=4)c.lineTo(x,wy(x,o)+dy);c.lineTo(248,230);c.quadraticCurveTo(248,244,234,244);c.closePath();c.fill();c.stroke()}
|
||||
sea(2,-14)
|
||||
c.save();c.translate(128,170+b);c.rotate(r);c.translate(-128,-170)
|
||||
c.fillStyle=BR
|
||||
c.beginPath();c.moveTo(48,166);c.quadraticCurveTo(14,170,10,148);c.quadraticCurveTo(26,156,50,152);c.fill();c.stroke()
|
||||
for(const[x,a]of[[56,-.5],[76,-.2]])c.save(),c.translate(x,150),c.rotate(a),c.beginPath(),c.ellipse(0,-14,9,16,0,0,T),c.fill(),c.stroke(),c.restore()
|
||||
c.beginPath();c.ellipse(116,168,76,30,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=BE;c.beginPath();c.ellipse(118,160,56,18,0,0,T);c.fill()
|
||||
c.fillStyle=BR;c.beginPath();c.arc(194,140,36,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=BE;c.beginPath();c.ellipse(204,150,22,16,0,0,T);c.fill()
|
||||
for(const[x,y]of[[176,108],[216,112]])c.fillStyle=BR,c.beginPath(),c.arc(x,y,8,0,T),c.fill(),c.stroke()
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(206,142,6,4,0,0,T);c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(206,146);c.lineTo(206,152);c.moveTo(196,154);c.quadraticCurveTo(206,160,216,154);c.stroke()
|
||||
for(const[x,y]of[[184,128],[220,130]])c.beginPath(),bang?(c.moveTo(x-6,y-4),c.lineTo(x+2,y),c.lineTo(x-6,y+4)):c.arc(x,y+2,6,1.15*PI,1.85*PI),c.stroke()
|
||||
c.lineWidth=3;for(const d of[-1,1])c.beginPath(),c.moveTo(222,150+d*3),c.lineTo(236,148+d*6),c.stroke()
|
||||
c.fillStyle=BL;c.beginPath();c.ellipse(180,148,7,4,0,0,T);c.fill()
|
||||
c.lineWidth=7
|
||||
c.fillStyle=ST;c.beginPath();c.ellipse(118,140,22,12,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=SD;c.beginPath();c.ellipse(112,136,6,3,0,0,T);c.fill()
|
||||
const cy=118-26*h
|
||||
c.save();c.translate(122,cy);c.rotate(-.2)
|
||||
c.fillStyle=CL;c.beginPath();c.moveTo(-18,4);c.quadraticCurveTo(0,-26,18,4);c.quadraticCurveTo(0,12,-18,4);c.fill();c.stroke()
|
||||
c.lineWidth=3;c.strokeStyle=CD;for(const a of[-.5,0,.5])c.beginPath(),c.moveTo(0,6),c.lineTo(sin(a)*14,-10+abs(a)*6),c.stroke()
|
||||
c.restore();c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.fillStyle=BR;for(const d of[-1,1])c.beginPath(),c.moveTo(d<0?98:146,154),c.quadraticCurveTo(d<0?94:150,cy+16,122+d*20,cy+4),c.lineWidth=16,c.stroke(),c.strokeStyle=BR,c.lineWidth=6,c.stroke(),c.strokeStyle='#111',c.lineWidth=7,c.beginPath(),c.arc(122+d*20,cy+4,9,0,T),c.fill(),c.stroke()
|
||||
if(bang){c.lineWidth=4;for(const[a,l]of[[-2.5,14],[-1.9,16],[-.6,14],[-1.25,16]])c.beginPath(),c.moveTo(122+cos(a)*30,130+sin(a)*22),c.lineTo(122+cos(a)*(30+l),130+sin(a)*(22+l)),c.stroke();c.lineWidth=7}
|
||||
c.restore()
|
||||
sea(0,6)
|
||||
c.strokeStyle=WL;c.lineWidth=4;for(const[x,y,w]of[[60,224,18],[150,230,24],[210,222,14]])c.beginPath(),c.moveTo(x-w,y+2*sin(T*t+x)),c.lineTo(x+w,y+2*sin(T*t+x)),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// stack of pancakes on a plate, the butter pat softening on top while blobs of syrup run down the sides
|
||||
const{sin,PI,min,max,sqrt}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const PC='#ffc078',PT='#ffd8a8',SY='#b5651d',SL='#e8a35a',BU='#ffe066',BS='#fcc419',PL='#e7f5ff',BL='#ffa8a8'
|
||||
const DR=[[70,60],[88,64],[170,64],[190,56]]
|
||||
export default(c,t)=>{
|
||||
c.fillStyle=PL;c.beginPath();c.ellipse(128,214,112,24,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.ellipse(128,212,88,15,0,0,T);c.stroke();c.lineWidth=7
|
||||
c.fillStyle=SY;c.beginPath();c.ellipse(128,206,100,15,0,0,T);c.fill();c.stroke()
|
||||
for(let k=0;k<3;k++){const y=200-k*28;c.fillStyle=PC;c.beginPath();c.ellipse(128,y,86,18,0,0,PI);c.lineTo(42,y-22);c.ellipse(128,y-22,86,18,0,PI,T);c.closePath();c.fill();c.stroke()}
|
||||
c.fillStyle=PT;c.beginPath();c.ellipse(128,122,86,18,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=SY;c.beginPath();for(let a=0;a<=T+.01;a+=.1)c.lineTo(128+Math.cos(a)*(64+5*sin(a*5)),122+sin(a)*(12+2*sin(a*5)));c.closePath();c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
const m=(1+sin(T*t))/2
|
||||
c.fillStyle='#fff3bf';c.beginPath();c.ellipse(128,118,30+6*m,8+2*m,0,0,T);c.fill()
|
||||
c.fillStyle=BS;c.beginPath();c.moveTo(104,116);c.lineTo(128,128);c.lineTo(152,116);c.lineTo(152,116-10+3*m);c.lineTo(128,128-10+3*m);c.lineTo(104,116-10+3*m);c.closePath();c.fill();c.lineWidth=5;c.stroke()
|
||||
const top=116-10+3*m;c.fillStyle=BU;c.beginPath();c.moveTo(104,top);c.quadraticCurveTo(116,top-14,128,top-13);c.quadraticCurveTo(142,top-14,152,top);c.lineTo(128,top+12);c.closePath();c.fill();c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=3.5;c.beginPath();c.moveTo(116,top-4);c.lineTo(126,top-8);c.stroke();c.strokeStyle='#111'
|
||||
DR.forEach(([x,L],k)=>{
|
||||
const p=(t+k*.27)%1,y0=122+18*sqrt(1-((x-128)/86)**2)-6,yb=y0+L*min(1,p/.6),ya=y0+L*max(0,(p-.6)/.4)
|
||||
for(const[w,s]of[[15,'#111'],[8,SY]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x,ya),c.lineTo(x,yb),c.stroke()
|
||||
c.fillStyle=SY;c.lineWidth=5;c.strokeStyle='#111';c.beginPath();c.arc(x,yb+2,8,0,PI);c.stroke();c.beginPath();c.arc(x,yb+1,6.5,0,T);c.fill()
|
||||
c.strokeStyle=SL;c.lineWidth=3;c.beginPath();c.moveTo(x-2,ya+3);c.lineTo(x-2,max(ya+3,yb-6));c.stroke();c.strokeStyle='#111'
|
||||
})
|
||||
c.lineWidth=7
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*20,151,5.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*20-2,149,2,0,T),c.fill()
|
||||
c.lineWidth=4.5;c.beginPath();c.arc(128,154,7,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*29,158,6,3.5,0,0,T),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// peacock fanning its tail open into a ring of eye feathers, shimmying, then folding it back up
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=12,delay=100
|
||||
const TL='#38d9a9',TD='#12b886',GO='#ffd43b',EB='#4dabf7',ED='#1864ab',BD='#4dabf7',BK='#1c7ed6',OR='#ffa94d',BL='#ffa8a8'
|
||||
const ease=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
export default(c,t)=>{
|
||||
const s=ease(t/.25)-ease((t-.7)/.25),sh=sin(4*T*t+.8)*s**6,N=9
|
||||
// all feather outlines first, so a folded bunch doesn't turn into a black mass, then fills with a thin teal seam
|
||||
const fe=[...Array(N)].map((_,k)=>{const u=(k-(N-1)/2)/((N-1)/2);return[u*(.45+.95*s)+.05*sh*u,84+32*s]})
|
||||
const go=(a,f)=>{c.save();c.translate(128,170);c.rotate(a);f();c.restore()}
|
||||
for(const[a,L]of fe)go(a,()=>{c.lineWidth=14;c.beginPath();c.ellipse(0,-L*.55,15+5*s,L*.55,0,0,T);c.stroke()})
|
||||
for(const[a,L]of fe)go(a,()=>{
|
||||
c.fillStyle=TL;c.strokeStyle=TD;c.lineWidth=3;c.beginPath();c.ellipse(0,-L*.55,15+5*s,L*.55,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;c.beginPath();c.moveTo(0,-8);c.lineTo(0,-L+20);c.stroke();c.strokeStyle='#111'
|
||||
c.fillStyle=GO;c.lineWidth=5;c.beginPath();c.ellipse(0,-L+16,12,15,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=EB;c.beginPath();c.ellipse(0,-L+17,7,9,0,0,T);c.fill()
|
||||
c.fillStyle=ED;c.beginPath();c.ellipse(0,-L+18,3.5,5,0,0,T);c.fill()
|
||||
})
|
||||
c.lineWidth=7
|
||||
c.fillStyle=OR;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*14,228,12,6,0,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=12;c.beginPath();for(const d of[-1,1])c.moveTo(128+d*12,206),c.lineTo(128+d*14,224);c.stroke()
|
||||
c.strokeStyle=OR;c.lineWidth=5;c.beginPath();for(const d of[-1,1])c.moveTo(128+d*12,206),c.lineTo(128+d*14,224);c.stroke();c.strokeStyle='#111';c.lineWidth=7
|
||||
for(const[x,y]of[[116,52],[128,46],[140,52]])c.lineWidth=4,c.beginPath(),c.moveTo(128,78),c.lineTo(x,y),c.stroke(),c.lineWidth=5,c.fillStyle=BD,c.beginPath(),c.arc(x,y,6,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7
|
||||
const sil=()=>{c.beginPath();c.ellipse(128,176,34,40,0,0,T);c.moveTo(110,152);c.lineTo(114,104);c.lineTo(142,104);c.lineTo(146,152);c.closePath();c.moveTo(152,98);c.arc(128,98,24,0,T)}
|
||||
sil();c.lineWidth=14;c.stroke();c.fillStyle=BD;sil();c.fill();c.lineWidth=7
|
||||
c.fillStyle=BK;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*26,180,10,26,-d*.2,0,T),c.fill(),c.lineWidth=5,c.stroke()
|
||||
c.lineWidth=7
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*11,94,8,10,0,0,T),c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*11,95,4.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(127+d*11,93,1.6,0,T),c.fill()
|
||||
c.fillStyle=GO;c.lineWidth=4;c.beginPath();c.moveTo(122,104);c.lineTo(134,104);c.lineTo(128,114);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*17,108,5,3,0,0,T),c.fill()
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// striped donkey piñata swinging on its rope, bonked by a stick from below, candy popping out and falling
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
const ST=['#f783ac','#ffd43b','#4dabf7','#69db7c'],PINK='#faa2c1',SN='#ffd8a8',ROPE='#e0a96d',STICK='#a9744f',CANDY=['#ff6b6b','#b197fc','#ffd43b','#38d9a9','#ffa94d','#4dabf7']
|
||||
const parts=[
|
||||
c=>c.roundRect(-54,0,94,56,16),
|
||||
c=>{c.moveTo(12,10);c.lineTo(24,-30);c.lineTo(46,-26);c.lineTo(38,16);c.closePath()},
|
||||
c=>c.roundRect(22,-54,64,34,14),
|
||||
c=>c.ellipse(36,-62,6,16,-.25,0,T),
|
||||
c=>{c.moveTo(56,-62);c.ellipse(50,-62,6,16,.25,0,T)},
|
||||
...[-46,-26,4,24].map(x=>c=>c.roundRect(x,48,14,28,4))
|
||||
]
|
||||
const burst=(c,x,y,s)=>{c.fillStyle='#fff9db';c.lineWidth=5;c.beginPath();for(let k=0;k<16;k++){const r=k%2?s*.45:s,a=k*PI/8;c.lineTo(x+cos(a)*r,y+sin(a)*r)}c.closePath();c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const a=.18*cos(T*t),w=(t+.12)%1,hit=t<.14
|
||||
c.save();c.translate(132,-40);c.rotate(a)
|
||||
for(const[lw,st]of[[11,'#111'],[5,ROPE]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.moveTo(0,0),c.lineTo(0,152),c.stroke()
|
||||
c.strokeStyle='#111';c.translate(0,150);c.rotate(-a*.4);c.scale(.9,.9)
|
||||
for(const[x,col]of[[-58,ST[0]],[-62,ST[1]],[-66,ST[2]]])for(const[lw,st]of[[9,'#111'],[4,col]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.moveTo(-52,12),c.lineTo(x,40+(x+58)*-2),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
c.lineWidth=14;for(const p of parts)c.beginPath(),p(c),c.stroke()
|
||||
c.fillStyle=PINK;for(const p of parts)c.beginPath(),p(c),c.fill()
|
||||
c.save();c.beginPath();parts[0](c);parts[1](c);c.clip()
|
||||
for(let k=0;k<8;k++){c.fillStyle=ST[k%4];c.beginPath();c.moveTo(-60,-34+k*12);for(let x=-60;x<=50;x+=10)c.lineTo(x+5,-34+k*12+6),c.lineTo(x+10,-34+k*12);c.lineTo(50,-34+k*12+14);c.lineTo(-60,-34+k*12+14);c.fill()}
|
||||
c.restore()
|
||||
c.save();c.beginPath();parts[2](c);c.clip();c.fillStyle=ST[1];c.beginPath();c.moveTo(22,-54);for(let x=22;x<=60;x+=8)c.lineTo(x+4,-42),c.lineTo(x+8,-54);c.fill()
|
||||
c.fillStyle=SN;c.beginPath();c.ellipse(80,-36,14,15,0,0,T);c.fill();c.restore()
|
||||
;[-46,-26,4,24].forEach((x,k)=>{c.fillStyle=ST[(k+2)%4];c.beginPath();c.roundRect(x,48,14,28,4);c.fill()})
|
||||
c.lineWidth=4;for(const p of[parts[0],...parts.slice(5)])c.beginPath(),p(c),c.stroke()
|
||||
c.fillStyle='#111';c.lineWidth=3.5
|
||||
if(hit){c.beginPath();c.moveTo(50,-44);c.lineTo(58,-39);c.lineTo(50,-34);c.stroke()}
|
||||
else c.beginPath(),c.arc(54,-40,4,0,T),c.fill()
|
||||
c.beginPath();c.arc(84,-38,2.2,0,T);c.fill()
|
||||
c.beginPath();if(hit)c.ellipse(72,-26,4,3,0,0,T),c.fill();else c.arc(72,-30,5,.2*PI,.8*PI),c.stroke()
|
||||
c.restore()
|
||||
const sw=w<.12?sin(PI/2*w/.12):w<.3?cos(PI/2*(w-.12)/.18):0
|
||||
if(sw>0){
|
||||
const ph=-.08-1.356*sw
|
||||
c.save();c.translate(40,300);c.rotate(ph);c.lineWidth=7
|
||||
c.fillStyle=STICK;c.beginPath();c.moveTo(0,-7);c.lineTo(150,-11);c.quadraticCurveTo(158,0,150,11);c.lineTo(0,7);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const x of[96,116,136])c.beginPath(),c.moveTo(x,-10),c.lineTo(x-6,10),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
if(t<.16)burst(c,60,152,22*sin(PI*t/.16)+8)
|
||||
if(t<.62){
|
||||
const u=t
|
||||
for(let k=0;k<6;k++){
|
||||
const vx=-30+k*32,x=93+vx*u,y=157-110*u+380*u*u,s=u<.45?1:(.62-u)/.17
|
||||
if(y>270||s<=0)continue
|
||||
c.save();c.translate(x,y);c.rotate(k*1.3+u*9);c.scale(s,s);c.fillStyle=CANDY[k];c.lineWidth=4
|
||||
for(const d of[-1,1])c.beginPath(),c.moveTo(d*8,0),c.lineTo(d*17,-7),c.lineTo(d*17,7),c.closePath(),c.fill(),c.stroke()
|
||||
c.beginPath();c.ellipse(0,0,10,8,0,0,T);c.fill();c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// pineapple in sunglasses grooving side to side to the beat, crown leaves swaying behind it and music notes popping up
|
||||
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||
export const frames=14,delay=90
|
||||
const PA='#ffd43b',PD='#f59f00',LF='#69db7c',LD='#40c057',BL='#ffa8a8',NC=['#9775fa','#4dabf7']
|
||||
const note=(c,x,y,s,col)=>{
|
||||
c.save();c.translate(x,y);c.scale(s,s);c.rotate(-.2)
|
||||
for(const[w,st]of[[10,'#111'],[4,col]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(8,4),c.lineTo(8,-26),c.quadraticCurveTo(18,-20,20,-10),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5;c.fillStyle=col;c.beginPath();c.ellipse(0,4,10,7,-.4,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const r=.13*sin(T*t),b=-5*abs(sin(2*T*t))
|
||||
;[0,1].forEach(k=>{const p=(t+k*.5)%1;note(c,k?54:202,104-64*p,sin(PI*p),NC[k])})
|
||||
c.strokeStyle='#111'
|
||||
c.save();c.translate(128,234+b);c.rotate(r);c.translate(-128,-234)
|
||||
;[[-1.05,52],[1.05,52],[-.6,64],[.6,64],[-.25,76],[.25,76],[0,66]].forEach(([a,L],k)=>{
|
||||
c.save();c.translate(128,96);c.rotate(a+.14*sin(T*t-1.1-k*.2));c.fillStyle=k%2?LD:LF
|
||||
c.beginPath();c.moveTo(-11,6);c.quadraticCurveTo(-9,-L*.6,0,-L);c.quadraticCurveTo(9,-L*.6,11,6);c.closePath();c.fill();c.lineWidth=6;c.stroke();c.restore()
|
||||
})
|
||||
c.lineWidth=7;c.fillStyle=PA;c.beginPath();c.ellipse(128,164,62,70,0,0,T);c.fill()
|
||||
c.save();c.clip();c.strokeStyle=PD;c.lineWidth=4
|
||||
for(let k=-8;k<9;k++)c.beginPath(),c.moveTo(128+k*24-90,90),c.lineTo(128+k*24+90,240),c.stroke(),c.beginPath(),c.moveTo(128+k*24+90,90),c.lineTo(128+k*24-90,240),c.stroke()
|
||||
c.restore();c.strokeStyle='#111';c.beginPath();c.ellipse(128,164,62,70,0,0,T);c.stroke()
|
||||
c.fillStyle='#343a40';for(const d of[-1,1])c.beginPath(),c.roundRect(128+d*24-21,128,42,28,[6,6,14,14]),c.fill(),c.stroke()
|
||||
c.lineWidth=6;c.beginPath();c.moveTo(118,134);c.quadraticCurveTo(128,128,138,134);c.stroke()
|
||||
c.strokeStyle='#fff';c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*24-12,148),c.lineTo(128+d*24-2,136),c.stroke()
|
||||
c.strokeStyle='#111';c.fillStyle='#111';c.beginPath();c.moveTo(112,176);c.quadraticCurveTo(128,196,146,174);c.quadraticCurveTo(128,182,112,176);c.closePath();c.fill();c.lineWidth=4;c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*42,174,9,5,0,0,T),c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
// two-tone popsicle slowly melting, drips swelling on its bottom edge and falling into a little puddle
|
||||
// the body and its drips are stroked wide first and filled after, so they read as one outline
|
||||
const{sin,PI,min}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const PK='#f783ac',YE='#ffd43b',STK='#e0a96d',BL='#ffa8a8',SW='#a5d8ff',DX=[98,154]
|
||||
const body=c=>{c.beginPath();c.moveTo(178,170);c.lineTo(178,64);c.bezierCurveTo(178,20,78,20,78,64);c.lineTo(78,170);for(let k=0;k<5;k++)c.quadraticCurveTo(88+k*20,k%2?166:180,98+k*20,172);c.closePath()}
|
||||
export default(c,t)=>{
|
||||
const dr=DX.map((x,k)=>{const p=(t+k*.5)%1,g=min(1,p/.65);return{x,p,L:p<.65?6+30*g:6,r:p<.65?5+4.5*g:5}})
|
||||
const tongue=({x,L,r})=>{c.beginPath();c.moveTo(x-12,164);c.quadraticCurveTo(x-7,172+L*.5,x-r,172+L);c.arc(x,172+L,r,PI,0,true);c.quadraticCurveTo(x+7,172+L*.5,x+12,164);c.closePath()}
|
||||
c.fillStyle=YE;c.beginPath();c.ellipse(128,230,78,12,0,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const d of dr)if(d.p>.8){const q=(d.p-.8)/.2;c.beginPath();c.ellipse(d.x,230,6+20*q,2+4*q,0,0,T);c.stroke()}
|
||||
c.lineWidth=7
|
||||
c.fillStyle=STK;c.beginPath();c.roundRect(114,150,28,82,[0,0,12,12]);c.fill();c.stroke()
|
||||
c.lineWidth=14;body(c);c.stroke();for(const d of dr)tongue(d),c.stroke()
|
||||
c.save();body(c);c.clip();c.fillStyle=YE;c.fillRect(70,20,116,170);c.fillStyle=PK;c.beginPath();c.moveTo(70,20);c.lineTo(186,20);for(let x=186;x>=70;x-=4)c.lineTo(x,104+6*sin(x/11));c.closePath();c.fill()
|
||||
c.strokeStyle='#fff';c.lineWidth=8;c.beginPath();c.moveTo(94,56);c.lineTo(94,86);c.stroke();c.restore()
|
||||
c.fillStyle=YE;for(const d of dr)tongue(d),c.fill()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*22,128,6,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*22-2,126,2.2,0,T),c.fill()
|
||||
c.lineWidth=4.5;c.beginPath();c.moveTo(116,144);for(let k=1;k<=4;k++)c.lineTo(116+k*6,k%2?140:144);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*38,142,8,4.5,0,0,T),c.fill()
|
||||
c.fillStyle=SW;c.lineWidth=4;c.beginPath();c.moveTo(164,74);c.quadraticCurveTo(172,90,164,94);c.quadraticCurveTo(156,90,164,74);c.fill();c.stroke()
|
||||
c.lineWidth=6
|
||||
for(const d of dr)if(d.p>=.65&&d.p<.8){const y=200+(d.p-.65)/.15*26;c.fillStyle=YE;c.beginPath();c.moveTo(d.x,y-12);c.quadraticCurveTo(d.x+7,y-2,d.x+6,y+2);c.arc(d.x,y+2,6,0,PI);c.quadraticCurveTo(d.x-7,y-2,d.x,y-12);c.fill();c.stroke()}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
// coaster car with a cheering rider racing around a loop-the-loop on a track held up by striped supports
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const RA='#ff6b6b',SU='#4dabf7',CA='#ffd43b',CD='#fab005',SKIN='#ffd8a8',HAIR='#a9744f',GR='#69db7c',BL='#ffa8a8'
|
||||
const CX=128,CY=106,R=68,Y0=CY+R,X0=-44,X1=300,L1=CX-X0,L2=T*R,L3=X1-CX
|
||||
// position and heading along the track by distance: in from the left, once round the loop, out to the right
|
||||
const at=s=>s<L1?[X0+s,Y0,0]:s<L1+L2?(a=>[CX+R*cos(a),CY+R*sin(a),PI/2-a])(PI/2-(s-L1)/R):[CX+s-L1-L2,Y0,0]
|
||||
export default(c,t)=>{
|
||||
c.fillStyle=GR;c.beginPath();c.roundRect(10,230,236,14,7);c.fill();c.stroke()
|
||||
for(const[x,y]of[[30,Y0],[CX-46,CY+50],[CX,Y0],[CX+46,CY+50],[226,Y0]]){for(const[w,s]of[[13,'#111'],[5,SU]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(x,y),c.lineTo(x,231),c.stroke()}
|
||||
for(const[w,s]of[[15,'#111'],[7,RA]]){c.lineWidth=w;c.strokeStyle=s;c.beginPath();c.arc(CX,CY,R,0,T);c.stroke();c.beginPath();c.moveTo(4,Y0);c.lineTo(252,Y0);c.stroke()}
|
||||
c.strokeStyle='#111'
|
||||
const[x,y,a]=at((t*(L1+L2+L3)+90)%(L1+L2+L3))
|
||||
c.save();c.translate(x,y);c.rotate(-a)
|
||||
for(const[w,s]of[[9,'#111'],[3,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(-30,-14),c.lineTo(-46,-14),c.moveTo(-30,-24),c.lineTo(-42,-24),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
for(const[w,s]of[[9,'#111'],[4,SKIN]])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.moveTo(-10,-34),c.lineTo(-18,-50),c.moveTo(2,-34),c.lineTo(8,-50),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5
|
||||
c.fillStyle=HAIR;c.beginPath();c.arc(-4,-38,10,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=SKIN;c.beginPath();c.arc(-3,-36,8,0,PI);c.fill()
|
||||
c.lineWidth=6;c.fillStyle=CA;c.beginPath();c.roundRect(-24,-30,48,22,7);c.fill();c.stroke()
|
||||
c.fillStyle=CD;c.beginPath();c.roundRect(-24,-14,48,6,3);c.fill()
|
||||
c.fillStyle='#111';c.beginPath();c.arc(12,-21,3,0,T);c.fill()
|
||||
c.lineWidth=3;c.beginPath();c.arc(16,-18,4,.2*PI,.9*PI);c.stroke()
|
||||
c.fillStyle='#495057';c.lineWidth=4;for(const wx of[-13,13])c.beginPath(),c.arc(wx,-6,5,0,T),c.fill(),c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
// snow globe gets a shake, snow swirls around a tiny house and pine inside, then drifts down and settles
|
||||
// each flake lifts off its resting spot, swirls, and lands back on the same spot, so the loop is seamless
|
||||
const{sin,cos,PI,abs,min}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const GL='#d0ebff',BS='#a9744f',BAND='#ffd43b',RF='#ff6b6b',WL='#ffd8a8',WIN='#ffd43b',PN='#51cf66',BR='#8d6346'
|
||||
const F=[...Array(14)].map((_,j)=>({gx:62+j*9.6,gy:178-(j%3)*5,r:24+(j*37)%56,q:j*2.4}))
|
||||
const sm=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
export default(c,t)=>{
|
||||
const u=t/.32,sh=t<.32?.15*sin(PI*u)*sin(3*T*u):0,cx=128,cy=108,R=90
|
||||
if(abs(sh)>.05){const d=sh>0?1:-1;for(const r of[104,118])for(const[w,s]of[[10,'#111'],[4,'#fff']])c.lineWidth=w,c.strokeStyle=s,c.beginPath(),c.arc(128,140,r,d>0?-.3:PI-.3,d>0?.3:PI+.3),c.stroke()}
|
||||
c.strokeStyle='#111';c.save();c.translate(128,240);c.rotate(sh);c.translate(-128,-240)
|
||||
const glob=()=>{c.beginPath();c.arc(cx,cy,R,0,T)}
|
||||
glob();c.fillStyle=GL;c.fill()
|
||||
c.save();glob();c.clip()
|
||||
c.lineWidth=6;c.fillStyle='#fff';c.beginPath();c.ellipse(128,192,100,32,0,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=BR;c.lineWidth=5;c.beginPath();c.rect(162,150,10,14);c.fill();c.stroke()
|
||||
for(const[w,y0,h]of[[28,154,28],[22,134,26],[16,114,24]]){c.fillStyle=PN;c.beginPath();c.moveTo(167-w,y0);c.lineTo(167,y0-h);c.lineTo(167+w,y0);c.closePath();c.fill();c.stroke();c.fillStyle='#fff';c.beginPath();c.moveTo(167-w*.4,y0-h*.6);c.lineTo(167,y0-h);c.lineTo(167+w*.4,y0-h*.6);c.quadraticCurveTo(167,y0-h*.45,167-w*.4,y0-h*.6);c.fill()}
|
||||
c.fillStyle=WL;c.beginPath();c.rect(80,128,46,36);c.fill();c.stroke()
|
||||
c.fillStyle=BR;c.beginPath();c.rect(110,96,10,20);c.fill();c.stroke()
|
||||
c.fillStyle=RF;c.beginPath();c.moveTo(72,132);c.lineTo(103,102);c.lineTo(134,132);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.moveTo(84,120);c.lineTo(103,102);c.lineTo(122,120);c.quadraticCurveTo(103,112,84,120);c.fill();c.stroke()
|
||||
c.fillStyle=WIN;c.beginPath();c.rect(86,138,14,12);c.fill();c.stroke();c.fillStyle=BR;c.beginPath();c.rect(106,144,12,20);c.fill();c.stroke()
|
||||
for(const f of F){
|
||||
const sw=k=>[cx+f.r*cos(f.q+k*T*1.6),cy-8+f.r*.85*sin(f.q+k*T*1.6)]
|
||||
let x,y,rr
|
||||
if(t<.12){const b=sm(t/.12),[sx,sy]=sw(t);x=f.gx+(sx-f.gx)*b;y=f.gy+(sy-f.gy)*b;rr=min(1,b*4)}
|
||||
else if(t<.4){[x,y]=sw(t);rr=1}
|
||||
else{const e=sm((t-.4)/.6),[sx,sy]=sw(.4);x=sx+(f.gx-sx)*e+8*(1-e)*sin(e*T*2+f.q);y=sy+(f.gy-sy)*e;rr=min(1,(1-e)*5)}
|
||||
if(rr>.05){c.fillStyle='#fff';c.lineWidth=2;c.beginPath();c.arc(x,y,3.8*rr,0,T);c.fill();c.stroke()}
|
||||
}
|
||||
c.restore()
|
||||
c.strokeStyle='#fff';c.lineWidth=8;c.beginPath();c.arc(cx,cy,R-16,PI*1.08,PI*1.38);c.stroke();c.lineWidth=6;c.beginPath();c.arc(cx,cy,R-16,PI*1.45,PI*1.53);c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7;glob();c.stroke()
|
||||
c.fillStyle=BS;c.beginPath();c.moveTo(64,184);c.lineTo(192,184);c.lineTo(210,240);c.lineTo(46,240);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=BAND;c.beginPath();c.moveTo(58,202);c.lineTo(198,202);c.lineTo(203,218);c.lineTo(53,218);c.closePath();c.fill();c.lineWidth=5;c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// soccer ball kicked spinning into the goal, the net bulging back around it, then a fresh ball bounces in to start again
|
||||
const{sin,cos,PI,abs,max,min,exp,hypot}=Math,T=2*PI
|
||||
export const frames=24,delay=70
|
||||
const GR='#69db7c',GRD='#51cf66',NET='#adb5bd'
|
||||
const ball=(c,x,y,r,a)=>{
|
||||
if(r<1)return
|
||||
c.save();c.translate(x,y);c.rotate(a)
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(0,0,r,0,T);c.fill()
|
||||
c.save();c.clip();c.fillStyle='#111'
|
||||
const pent=(px,py,s)=>{c.beginPath();for(let k=0;k<5;k++){const b=k*T/5-PI/2;c.lineTo(px+cos(b)*s,py+sin(b)*s)}c.closePath();c.fill()}
|
||||
pent(0,0,r*.34);c.lineWidth=max(2,r*.08);c.strokeStyle='#111'
|
||||
for(let k=0;k<5;k++){const b=k*T/5-PI/2;pent(cos(b)*r*.98,sin(b)*r*.98,r*.32);c.beginPath();c.moveTo(cos(b)*r*.34,sin(b)*r*.34);c.lineTo(cos(b)*r*.7,sin(b)*r*.7);c.stroke()}
|
||||
c.restore();c.lineWidth=max(3,r*.2);c.beginPath();c.arc(0,0,r,0,T);c.stroke();c.restore()
|
||||
}
|
||||
const lerp=(a,b,p)=>a+(b-a)*p
|
||||
export default(c,t)=>{
|
||||
// 0-.4 flight, .4-.7 net bulge and drop, .7-.82 ball pops away, .82-1 a fresh ball bounces in at the kick spot
|
||||
const S=[50,200,30],H=[178,124,17]
|
||||
let x,y,r,a=0,m=0,pop=0
|
||||
if(t<.4){const p=t/.4;x=lerp(S[0],H[0],p);y=lerp(S[1],H[1],p)-46*sin(PI*p);r=lerp(S[2],H[2],p);a=-p*T*1.5}
|
||||
else if(t<.7){const p=(t-.4)/.3;m=sin(PI*min(1,p*1.6))*(1-p*.3);x=H[0];y=lerp(H[1],178,p*p);r=H[2];a=-T*1.5-p*2}
|
||||
else if(t<.82){const p=(t-.7)/.12;x=H[0];y=178;r=H[2]*(1-p);a=0;pop=p}
|
||||
else{const p=(t-.82)/.18;x=S[0];y=S[1]-24*abs(sin(PI*p))*(1-p);r=S[2]*min(1,p*1.6)*(1+.15*sin(PI*min(1,p*1.6)));a=0}
|
||||
c.lineWidth=7;c.fillStyle=GR;c.beginPath();c.roundRect(8,192,240,52,14);c.fill();c.stroke()
|
||||
c.save();c.beginPath();c.roundRect(8,192,240,52,14);c.clip();c.fillStyle=GRD;for(const sx of[40,120,200])c.fillRect(sx,192,40,52);c.restore()
|
||||
c.beginPath();c.roundRect(8,192,240,52,14);c.stroke()
|
||||
// net: grid on the back panel, each point pulled toward the impact spot while the ball pushes in
|
||||
const P=(px,py)=>{const d=hypot(px-H[0],py-H[1]),k=m*.45*exp(-d*d/1800);return[px+(H[0]-px)*k,py+(H[1]-py)*k]}
|
||||
c.strokeStyle=NET;c.lineWidth=3
|
||||
for(let gx=100;gx<=228;gx+=16){c.beginPath();for(let gy=84;gy<=194;gy+=4)c.lineTo(...P(gx,gy));c.stroke()}
|
||||
for(let gy=84;gy<=194;gy+=14){c.beginPath();for(let gx=100;gx<=228;gx+=4)c.lineTo(...P(gx,gy));c.stroke()}
|
||||
c.beginPath();for(const[ax,ay,bx,by]of[[84,70,100,84],[244,70,228,84]])c.moveTo(ax,ay),c.lineTo(bx,by);c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
if(t>=.4&&t<.82)ball(c,x,y,r,a)
|
||||
if(pop>0){const s=8+18*pop;for(let k=0;k<6;k++){const b=k*T/6;for(const[w,st]of[[9,'#111'],[4,'#ffd43b']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(x+cos(b)*s,y+sin(b)*s),c.lineTo(x+cos(b)*(s+10*(1-pop)+2),y+sin(b)*(s+10*(1-pop)+2)),c.stroke()}c.strokeStyle='#111'}
|
||||
for(const[w,st]of[[16,'#111'],[8,'#fff']])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(84,196),c.lineTo(84,70),c.lineTo(244,70),c.lineTo(244,196),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
if(t<.4||t>=.82){c.fillStyle='#2f9e44';c.beginPath();c.ellipse(x,t<.4?lerp(226,196,t/.4):226,r*.8,r*.22,0,0,T);c.fill();ball(c,x,y,r,a)}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
// strawberry bouncing twice a loop with squash and stretch, its seeds jiggling and its leafy cap flapping behind
|
||||
const{sin,PI,abs,max,min}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
const RD='#ff6b6b',SD='#ffe066',LF='#69db7c',LD='#40c057',BL='#ffc9c9',SH='#ced4da'
|
||||
export default(c,t)=>{
|
||||
const u=(t*2)%1,H=54,h=H*4*u*(1-u),q=max(0,1-min(u,1-u)/.1),s=.1*abs(1-2*u)*(1-q)
|
||||
const sx=1+.18*q-.5*s,sy=1-.22*q+s,lag=.22*sin(2*T*t*2-1.2)
|
||||
c.fillStyle=SH;c.beginPath();c.ellipse(128,232,48*(1-.4*h/H)*(1+.2*q),7,0,0,T);c.fill()
|
||||
c.save();c.translate(128,228-h);c.scale(sx*.88,sy*.88);c.translate(0,-76)
|
||||
c.fillStyle=RD;c.beginPath();c.moveTo(0,-44);c.bezierCurveTo(46,-62,80,-28,70,8);c.bezierCurveTo(60,44,22,72,0,76);c.bezierCurveTo(-22,72,-60,44,-70,8);c.bezierCurveTo(-80,-28,-46,-62,0,-44);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=2.5;c.fillStyle=SD
|
||||
;[[-46,-20],[-20,-30],[22,-30],[48,-18],[-56,6],[56,6],[-40,34],[40,34],[-18,52],[18,52],[0,64],[-26,-2],[28,0]].forEach(([x,y],k)=>{const j=1.6*sin(2*T*t*2+k*1.7);c.beginPath();c.ellipse(x+j,y,3,4.5,x/90,0,T);c.fill();c.stroke()})
|
||||
c.lineWidth=7
|
||||
for(const[a,L]of[[-1.25,38],[1.25,38],[-.65,42],[.65,42],[0,40]]){
|
||||
c.save();c.translate(0,-48);c.rotate(PI+a+lag*(a?Math.sign(a):1)*.6);c.fillStyle=a?LF:LD;c.beginPath();c.moveTo(-10,0);c.quadraticCurveTo(-11,L*.6,0,L);c.quadraticCurveTo(11,L*.6,10,0);c.closePath();c.fill();c.stroke();c.restore()
|
||||
}
|
||||
for(const[w,st]of[[13,'#111'],[6,LD]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(0,-52),c.quadraticCurveTo(2,-66,10+lag*12,-74),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*22,6,6.5,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(d*22-2,4,2.4,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(0,14,9,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(d*40,20,9,5,0,0,T),c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// yellow submarine bobbing underwater, periscope turning, propeller spinning, bubbles rising past swaying seaweed
|
||||
const{sin,cos,PI,abs,min,max,round}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const Y='#ffd43b',YD='#fab005',GL='#a5d8ff',PR='#ced4da',SW='#51cf66',SA='#ffd8a8',BU='#d0ebff',BL='#ffa8a8'
|
||||
export default(c,t)=>{
|
||||
const b=round(5*sin(t*T)),th=t*T*4,pa=t*T,w=20*cos(pa)
|
||||
for(const[x,h,o]of[[34,74,0],[222,58,1.7]]){const s=8*sin(t*T+o);for(const[lw,st]of[[16,'#111'],[8,SW]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.moveTo(x,238),c.quadraticCurveTo(x-12,238-h*.5,x+s,238-h),c.stroke()}
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle=SA;c.beginPath();c.moveTo(8,246);c.quadraticCurveTo(128,206,248,246);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.lineWidth=4
|
||||
for(let k=0;k<3;k++){const p=(t+k/3)%1,s=3+5*p;c.fillStyle=BU;c.beginPath();c.arc(36+8*sin(p*T*2+k),146+b-p*118,s,0,T);c.fill();c.stroke()}
|
||||
c.save();c.translate(0,b)
|
||||
c.lineWidth=7
|
||||
c.fillStyle=YD;c.beginPath();c.moveTo(56,124);c.lineTo(40,100);c.lineTo(66,104);c.lineTo(84,122);c.closePath();c.fill();c.stroke()
|
||||
for(const[lw,st]of[[12,'#111'],[5,PR]])c.lineWidth=lw,c.strokeStyle=st,c.beginPath(),c.moveTo(144,100),c.lineTo(144,60),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5
|
||||
c.fillStyle=YD;c.beginPath();c.roundRect(144+min(0,w)-7,50,abs(w)+14,15,7);c.fill();c.stroke()
|
||||
c.fillStyle=GL
|
||||
if(abs(w)>5)c.beginPath(),c.ellipse(144+w,57.5,3,6,0,0,T),c.fill(),c.stroke()
|
||||
else if(sin(pa)>0)c.beginPath(),c.arc(144,57.5,5,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=YD;c.beginPath();c.roundRect(100,96,56,36,10);c.fill();c.stroke()
|
||||
c.fillStyle=PR;c.lineWidth=5;c.beginPath();c.roundRect(20,140,22,22,6);c.fill();c.stroke()
|
||||
for(const L of[22*cos(th),-22*cos(th),22*sin(th),-22*sin(th)])if(abs(L)>2)c.beginPath(),c.ellipse(18,151+L/2,5,abs(L/2),0,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=Y;c.beginPath();c.roundRect(36,118,188,66,33);c.fill();c.stroke()
|
||||
c.save();c.beginPath();c.roundRect(36,118,188,66,33);c.clip();c.fillStyle=YD;c.fillRect(30,168,200,20);c.restore()
|
||||
c.beginPath();c.roundRect(36,118,188,66,33);c.stroke()
|
||||
c.lineWidth=5;for(const x of[78,112,146]){c.fillStyle=GL;c.beginPath();c.arc(x,148,11,0,T);c.fill();c.stroke();c.fillStyle='#fff';c.beginPath();c.arc(x-4,144,3,0,T);c.fill()}
|
||||
c.fillStyle='#111';c.beginPath();c.ellipse(194,142,5,7,0,0,T);c.fill()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(192,139,2.5,0,T);c.fill()
|
||||
c.fillStyle=BL;c.beginPath();c.ellipse(182,160,8,5,0,0,T);c.fill()
|
||||
c.lineWidth=4;c.beginPath();c.arc(202,154,7,.2*PI,.8*PI);c.stroke()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// potted sunflower turning its smiley face to follow a little sun swinging across the sky, petals swaying
|
||||
const{sin,cos,PI,abs}=Math,T=2*PI
|
||||
export const frames=16,delay=100
|
||||
const PT='#ff922b',PD='#e8590c',ST='#51cf66',SD='#2f9e44',PE=['#fcc419','#ffd43b'],CE='#a9744f',CD='#7f5539',BL='#ff8787'
|
||||
const leaf=(c,x,y,a,L)=>{c.save();c.translate(x,y);c.rotate(a);c.fillStyle=ST;c.lineWidth=6;c.beginPath();c.moveTo(0,0);c.quadraticCurveTo(L*.5,-L*.38,L,0);c.quadraticCurveTo(L*.5,L*.38,0,0);c.fill();c.stroke();c.strokeStyle=SD;c.lineWidth=3;c.beginPath();c.moveTo(4,0);c.lineTo(L*.8,0);c.stroke();c.restore();c.strokeStyle='#111'}
|
||||
export default(c,t)=>{
|
||||
const s=sin(t*T),sx=128+94*s,sy=32+14*s*s,hx=128+12*s,hy=104,sq=1-.16*abs(s),w=.08*sin(2*t*T)
|
||||
c.save();c.translate(sx,sy);c.rotate(t*PI/4)
|
||||
for(let k=0;k<8;k++){const q=k*PI/4;for(const[lw,col]of[[10,'#111'],[4,'#ffd43b']])c.lineWidth=lw,c.strokeStyle=col,c.beginPath(),c.moveTo(cos(q)*22,sin(q)*22),c.lineTo(cos(q)*28,sin(q)*28),c.stroke()}
|
||||
c.restore();c.strokeStyle='#111';c.lineWidth=6;c.fillStyle='#ffd43b';c.beginPath();c.arc(sx,sy,16,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(sx+d*5,sy-1,2.2,0,T),c.fill()
|
||||
c.lineWidth=2.5;c.beginPath();c.arc(sx,sy+3,4,.15*PI,.85*PI);c.stroke()
|
||||
for(const[lw,col]of[[20,'#111'],[11,ST]])c.lineWidth=lw,c.strokeStyle=col,c.beginPath(),c.moveTo(128,200),c.quadraticCurveTo(128-6*s,160,hx,hy+20),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
leaf(c,127,176,-.5+w,44);leaf(c,127,160,PI+.45-w,40)
|
||||
c.lineWidth=7;c.fillStyle=PT;c.beginPath();c.moveTo(92,200);c.lineTo(164,200);c.lineTo(154,244);c.lineTo(102,244);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=PD;c.beginPath();c.roundRect(84,190,88,20,8);c.fill();c.stroke()
|
||||
c.save();c.translate(hx,hy);c.rotate(.2*s)
|
||||
c.lineWidth=5
|
||||
for(const[r,o,col]of[[44,PI/14,PE[0]],[40,0,PE[1]]])for(let k=0;k<14;k++){const q=k*T/14+o+.05*sin(2*t*T+k);c.fillStyle=col;c.beginPath();c.ellipse(cos(q)*r*sq,sin(q)*r,15,6.5,q,0,T);c.fill();c.stroke()}
|
||||
const fx=9*s
|
||||
c.lineWidth=7;c.fillStyle=CE;c.beginPath();c.ellipse(0,0,31*sq,31,0,0,T);c.fill();c.stroke()
|
||||
c.save();c.clip();c.fillStyle=CD;for(let y=-28;y<30;y+=9)for(let x=-28;x<30;x+=9)c.beginPath(),c.arc(x+(y/9&1)*4.5,y,1.8,0,T),c.fill();c.restore()
|
||||
c.fillStyle='#fff3bf';c.beginPath();c.ellipse(fx,6,20*sq,15,0,0,T);c.fill()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(fx+d*9*sq,1,4,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(fx+d*9*sq-1,-.5,1.5,0,T),c.fill()
|
||||
c.lineWidth=3.5;c.beginPath();c.arc(fx,7,5,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(fx+d*15*sq,9,4,2.5,0,0,T),c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
// sun sinks into the sea inside a round sticker while the sky warms to dusk, sparkles on the water, then it rises again
|
||||
const{sin,cos,PI,max}=Math,T=2*PI
|
||||
export const frames=16,delay=90
|
||||
const DAY=['#ffa94d','#ffc078','#ffd8a8','#fff3bf'],DUSK=['#7048e8','#9775fa','#f783ac','#ffa94d'],E=[0,60,98,130,156],BL='#ff8787'
|
||||
const mix=(a,b,k)=>'#'+[1,3,5].map(i=>Math.round(parseInt(a.slice(i,i+2),16)*(1-k)+parseInt(b.slice(i,i+2),16)*k).toString(16).padStart(2,'0')).join('')
|
||||
const spk=(c,x,y,s)=>{c.lineWidth=3;c.fillStyle='#fff';c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.2,-s*.2],[0,s,s*.2,s*.2],[-s,0,-s*.2,s*.2],[0,-s,-s*.2,-s*.2]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const k=(1-cos(t*T))/2,y=100+100*k,H=156,disc=()=>{c.beginPath();c.arc(128,128,112,0,T)}
|
||||
c.save();disc();c.clip()
|
||||
DAY.forEach((d,j)=>{c.fillStyle=mix(d,DUSK[j],k);c.fillRect(0,E[j],256,E[j+1]-E[j])})
|
||||
c.fillStyle=mix('#fff','#fcc2d7',k);c.lineWidth=5
|
||||
for(const[x,cy,w]of[[70,62,30],[186,86,24]])c.beginPath(),c.ellipse(x,cy,w,7,0,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=mix('#ffd43b','#ff922b',k);c.beginPath();c.arc(128,y,36,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111'
|
||||
if(k<.5)for(const d of[-1,1])c.beginPath(),c.arc(128+d*13,y-4,5,0,T),c.fill()
|
||||
else{c.lineWidth=4;for(const d of[-1,1])c.beginPath(),c.arc(128+d*13,y-7,6,.15*PI,.85*PI),c.stroke()}
|
||||
c.lineWidth=4;c.beginPath();c.arc(128,y+6,8,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(128+d*24,y+8,6,3.5,0,0,T),c.fill()
|
||||
c.fillStyle='#4dabf7';c.fillRect(0,H,256,100);c.fillStyle='#339af0';c.fillRect(0,H+46,256,60)
|
||||
c.lineWidth=7;c.beginPath();c.moveTo(0,H);c.lineTo(256,H);c.stroke()
|
||||
const L=(1-k)*42+12,sun=mix('#ffe066','#ff922b',k)
|
||||
for(const[j,dy]of[[0,14],[1,28],[2,42]]){const w=L*(1-j*.25),x=128+4*sin(2*t*T+j*2);for(const[lw,s]of[[11,'#111'],[5,sun]])c.lineWidth=lw,c.strokeStyle=s,c.beginPath(),c.moveTo(x-w,H+dy),c.lineTo(x+w,H+dy),c.stroke()}
|
||||
c.strokeStyle='#d0ebff';c.lineWidth=4
|
||||
for(const[x,cy]of[[42,184],[196,180],[70,218],[170,224]])for(const dx of[0,14])c.beginPath(),c.arc(x+dx,cy,7,PI*1.1,PI*1.9),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
for(const[x,cy,o]of[[60,200,0],[198,206,.5]])spk(c,x,cy,3+5*max(0,sin((t+o)*2*T)))
|
||||
c.restore();c.lineWidth=7;disc();c.stroke()
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
// salmon nigiri hopping on its wooden board, squishing on landing while a little wasabi buddy watches it go up and down
|
||||
const{sin,PI,abs}=Math,T=2*PI
|
||||
export const frames=20,delay=60
|
||||
const SA='#ffa94d',SS='#fff4e6',WA='#8ce99a',BD='#d4a373',BDD='#a9744f',BL='#ffa8a8'
|
||||
const salmon=c=>{c.beginPath();c.moveTo(-76,-50);c.bezierCurveTo(-72,-98,58,-106,82,-68);c.quadraticCurveTo(88,-50,72,-46);c.bezierCurveTo(32,-56,-34,-40,-66,-38);c.quadraticCurveTo(-80,-38,-76,-50);c.closePath()}
|
||||
export default(c,t)=>{
|
||||
const air=t<.7,h=air?72*sin(PI*t/.7):0,q=air?0:sin(PI*(t-.7)/.3),st=air?.07*abs(sin(2*PI*t/.7)):0
|
||||
const sx=1+.16*q-st,sy=1-.2*q+st
|
||||
c.fillStyle=BD;c.beginPath();c.roundRect(16,204,224,24,10);c.fill();c.stroke()
|
||||
c.fillStyle=BDD;c.beginPath();c.ellipse(112,216,62*sx*(1-h/72*.45),5,0,0,T);c.fill()
|
||||
c.lineWidth=4;c.strokeStyle=BDD;for(const[x,w]of[[34,26],[176,18]])c.beginPath(),c.moveTo(x,220),c.lineTo(x+w,220),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5
|
||||
c.fillStyle=WA;c.beginPath();c.moveTo(190,207);c.bezierCurveTo(188,184,200,178,210,170);c.quadraticCurveTo(206,162,214,154);c.quadraticCurveTo(220,166,222,174);c.bezierCurveTo(234,184,236,200,234,207);c.closePath();c.fill();c.stroke()
|
||||
const ly=-2.5*h/72
|
||||
for(const x of[205,220]){c.fillStyle='#111';c.beginPath();c.arc(x-1.5,192+ly,3.6,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(x-2.5,190.5+ly,1.3,0,T);c.fill()}
|
||||
c.lineWidth=3.5;c.beginPath();c.arc(212,198,4,.15*PI,.85*PI);c.stroke()
|
||||
c.lineWidth=7
|
||||
c.save();c.translate(112,210-h);c.scale(sx,sy)
|
||||
c.fillStyle='#fff';c.beginPath();c.roundRect(-62,-66,124,66,[26,26,14,14]);c.fill();c.stroke()
|
||||
c.lineWidth=3;for(const[x,y,a]of[[-46,-14,0],[46,-12,1],[-30,-6,1.5],[30,-5,2.5]])c.beginPath(),c.arc(x,y,5,a,a+1.6),c.stroke()
|
||||
c.lineWidth=7
|
||||
c.fillStyle=SA;salmon(c);c.fill()
|
||||
c.save();salmon(c);c.clip();c.strokeStyle=SS;c.lineWidth=7;for(let k=0;k<5;k++)c.beginPath(),c.moveTo(-70+k*36,-36),c.quadraticCurveTo(-58+k*36,-70,-42+k*36,-104),c.stroke();c.restore()
|
||||
salmon(c);c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*20,-30,6,0,T),c.fill()
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(d*20-2,-32,2.2,0,T),c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(0,-24,8,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(d*38,-18,8,4.5,0,0,T),c.fill()
|
||||
c.restore()
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// toucan perched on a branch, bobbing its huge colorful beak up and down and blinking
|
||||
// the black body gets a white rim so it doesn't vanish on dark backgrounds
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const BR='#a9744f',LF='#69db7c',BIB='#fff9db',OR='#ff922b',YE='#ffd43b',RD='#ff6b6b',TP='#e8590c',EB='#4dabf7',SK='#ffa94d'
|
||||
export default(c,t,i)=>{
|
||||
const a=.1*sin(2*T*t),b=Math.round(2*sin(2*T*t)),shut=i==6||i==7
|
||||
const D=(wd,cl,f)=>{for(const[l,s]of[[wd,'#111'],[wd-10,cl]])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
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.moveTo(70,184);c.lineTo(52,240);c.lineTo(82,240);c.lineTo(94,190);c.closePath()})
|
||||
D(20,BR,()=>{c.moveTo(16,212);c.quadraticCurveTo(128,204,240,214)})
|
||||
c.fillStyle=LF;c.beginPath();c.ellipse(222,228,16,8,.5,0,T);c.fill();c.stroke()
|
||||
c.save();c.translate(0,b)
|
||||
// body and head rimmed together so there is no white seam between them
|
||||
const bd=()=>{c.beginPath();c.ellipse(92,150,44,60,-.15,0,T)},hd=()=>{c.save();c.translate(104,120);c.rotate(a);c.beginPath();c.arc(0,-30,34,0,T);c.restore()}
|
||||
c.lineWidth=16;c.strokeStyle='#fff';bd();c.stroke();hd();c.stroke();c.fillStyle='#111';bd();c.fill();hd();c.fill();c.lineWidth=7;c.strokeStyle='#111'
|
||||
c.fillStyle=RD;c.beginPath();c.ellipse(96,198,18,10,-.2,0,T);c.fill();c.lineWidth=5;c.stroke();c.lineWidth=7
|
||||
c.save();c.translate(104,120);c.rotate(a)
|
||||
c.fillStyle=BIB;c.beginPath();c.ellipse(8,4,26,30,-.1,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=YE;c.beginPath();c.ellipse(10,24,18,8,0,0,T);c.fill()
|
||||
c.fillStyle=SK;c.beginPath();c.ellipse(12,-36,17,15,0,0,T);c.fill();c.lineWidth=5;c.stroke()
|
||||
c.fillStyle=EB;c.beginPath();c.arc(14,-36,10,0,T);c.fill();c.stroke()
|
||||
if(shut){c.beginPath();c.arc(14,-38,7,.15*PI,.85*PI);c.stroke()}
|
||||
else{c.fillStyle='#111';c.beginPath();c.arc(15,-36,5.5,0,T);c.fill();c.fillStyle='#fff';c.beginPath();c.arc(13,-38,2,0,T);c.fill()}
|
||||
c.lineWidth=7
|
||||
const beak=()=>{c.beginPath();c.moveTo(26,-44);c.bezierCurveTo(80,-66,128,-48,138,-14);c.quadraticCurveTo(136,-2,124,-6);c.quadraticCurveTo(80,-4,28,-8);c.closePath()}
|
||||
c.fillStyle=OR;beak();c.fill()
|
||||
c.save();beak();c.clip()
|
||||
c.fillStyle=YE;c.beginPath();c.moveTo(20,-80);c.quadraticCurveTo(80,-60,140,-40);c.lineTo(140,-80);c.closePath();c.fill()
|
||||
c.fillStyle=TP;c.beginPath();c.arc(136,-14,22,0,T);c.fill()
|
||||
c.fillStyle=RD;c.fillRect(20,-60,10,60)
|
||||
c.restore()
|
||||
c.lineWidth=5;c.beginPath();c.moveTo(30,-24);c.quadraticCurveTo(80,-26,132,-14);c.stroke();c.lineWidth=7
|
||||
beak();c.stroke()
|
||||
c.restore()
|
||||
c.restore()
|
||||
c.fillStyle=EB;for(const x of[84,104])c.lineWidth=5,c.beginPath(),c.ellipse(x,210,8,6,0,0,T),c.fill(),c.stroke()
|
||||
c.lineWidth=7
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
// traffic light cycling green, yellow, red, the lit lamp has a face that grins, panics, then glares
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=24,delay=90
|
||||
const HOUSE='#495057',HD='#343a40',POLE='#adb5bd',L=[['#ff6b6b','#6b3434'],['#ffd43b','#6b5f2c'],['#51cf66','#2c5a37']],DROP='#a5d8ff'
|
||||
export default(c,t,i)=>{
|
||||
const k=t<.42?2:t<.58?1:0
|
||||
c.fillStyle=POLE;c.beginPath();c.roundRect(114,200,28,52,6);c.fill();c.stroke()
|
||||
const h=()=>{c.beginPath();c.roundRect(70,8,116,206,30)}
|
||||
c.lineWidth=18;c.strokeStyle='#fff';h();c.stroke();c.fillStyle=HOUSE;h();c.fill();c.lineWidth=7;c.strokeStyle='#111';c.stroke()
|
||||
for(let j=0;j<3;j++){
|
||||
const y=46+j*65,on=j==k,[lc,dc]=L[j]
|
||||
c.fillStyle=HD;c.beginPath();c.arc(128,y,31,0,T);c.fill()
|
||||
if(on)for(const a of[-.5,0,.5,PI-.5,PI,PI+.5]){for(const[w,st]of[[9,'#111'],[3.5,lc]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(128+cos(a)*34,y+sin(a)*34),c.lineTo(128+cos(a)*42,y+sin(a)*42),c.stroke()}
|
||||
c.strokeStyle='#111';c.fillStyle=on?lc:dc;c.lineWidth=5;c.beginPath();c.arc(128,y,25,0,T);c.fill();c.stroke()
|
||||
c.fillStyle=on?'#fff':'#868e96';c.beginPath();c.ellipse(118,y-12,6,3.5,-.6,0,T);c.fill()
|
||||
if(!on)continue
|
||||
c.fillStyle='#111';c.lineWidth=3.5
|
||||
if(j==2){
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(128+d*9,y-2,5,PI*1.1,PI*1.9),c.stroke()
|
||||
c.beginPath();c.moveTo(118,y+5);c.quadraticCurveTo(128,y+20,138,y+5);c.closePath();c.fill()
|
||||
c.fillStyle='#ff8787';c.beginPath();c.ellipse(128,y+12,4,2.5,0,0,T);c.fill()
|
||||
}else if(j==1){
|
||||
c.fillStyle='#fff';for(const d of[-1,1])c.beginPath(),c.arc(128+d*9,y-3,6,0,T),c.fill(),c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(128+d*9,y-3+(i%2),2.5,0,T),c.fill()
|
||||
c.beginPath();c.ellipse(128,y+11,3.5,4.5,0,0,T);c.fill()
|
||||
c.fillStyle=DROP;c.lineWidth=3;const dy=(i%3)*2;c.beginPath();c.moveTo(150,y-16+dy);c.quadraticCurveTo(157,y-6+dy,150,y-4+dy);c.quadraticCurveTo(143,y-6+dy,150,y-16+dy);c.fill();c.stroke()
|
||||
}else{
|
||||
c.lineWidth=3.5;for(const d of[-1,1])c.beginPath(),c.moveTo(128+d*15,y-14),c.lineTo(128+d*5,y-9),c.stroke()
|
||||
for(const d of[-1,1])c.beginPath(),c.arc(128+d*9,y-3,3.5,0,T),c.fill()
|
||||
c.beginPath();c.arc(128,y+14,7,PI*1.15,PI*1.85);c.stroke()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
// unicorn prancing in place, front hooves lifting in turn, rainbow mane and tail flowing, a sparkle off the horn
|
||||
const{sin,cos,PI,abs,max}=Math,T=2*PI
|
||||
export const frames=16,delay=80
|
||||
const RB=['#ff6b6b','#ffa94d','#ffd43b','#69db7c','#4dabf7','#b197fc'],HN='#ffd43b',HO='#b197fc',FAR='#e9ecef',PK='#faa2c1'
|
||||
export default(c,t)=>{
|
||||
const b=-5*abs(sin(T*t)),l1=max(0,sin(T*t)),l2=max(0,-sin(T*t)),w=sin(T*t)
|
||||
const D=(wd,col,f)=>{for(const[l,s]of[[wd,'#111'],[wd-12,col]])c.lineWidth=l,c.strokeStyle=s,c.beginPath(),f(),c.stroke();c.lineWidth=7;c.strokeStyle='#111'}
|
||||
const leg=(x,y,l,col)=>{
|
||||
const kx=x+16*l,ky=y+30-6*l,fx=x+4*l,fy=226-30*l
|
||||
D(26,col,()=>{c.moveTo(x,y);c.lineTo(kx,ky);c.lineTo(fx,fy)})
|
||||
c.fillStyle=HO;c.beginPath();c.roundRect(fx-12,fy-4,24,14,5);c.fill();c.stroke()
|
||||
}
|
||||
// rainbow bundle: every strand stroked black and wide first, then the colors on top, so it reads as one outlined ribbon
|
||||
const bundle=(f)=>{
|
||||
for(let k=0;k<6;k++)c.lineWidth=20,c.beginPath(),f(k),c.stroke()
|
||||
for(let k=0;k<6;k++)c.lineWidth=8,c.strokeStyle=RB[k],c.beginPath(),f(k),c.stroke()
|
||||
c.lineWidth=7;c.strokeStyle='#111'
|
||||
}
|
||||
c.translate(0,b)
|
||||
leg(98,160,0,FAR);leg(164,160,l2,FAR)
|
||||
bundle(k=>{const o=k*6-15;c.moveTo(64,138+o*.4);c.bezierCurveTo(30+o,140+o*.3,26+8*w+o*.6,186,46+12*w-o*.3,214+o*.2)})
|
||||
leg(80,164,0,'#fff');leg(150,164,l1,'#fff')
|
||||
c.fillStyle='#fff';c.beginPath();c.moveTo(170,68);c.lineTo(176,40);c.lineTo(190,62);c.closePath();c.fill();c.stroke()
|
||||
const sil=()=>{c.beginPath();c.ellipse(118,146,62,36,0,0,T);c.moveTo(144,152);c.lineTo(160,96);c.lineTo(196,92);c.lineTo(182,150);c.closePath();c.moveTo(232,96);c.ellipse(198,86,34,24,.45,0,T)}
|
||||
sil();c.lineWidth=14;c.stroke();c.fillStyle='#fff';sil();c.fill();c.lineWidth=7
|
||||
c.fillStyle=PK;c.beginPath();c.ellipse(222,104,4,3,.4,0,T);c.fill()
|
||||
c.fillStyle=PK;c.beginPath();c.ellipse(196,100,9,5,.3,0,T);c.fill()
|
||||
c.lineWidth=5;c.beginPath();c.arc(188,82,8,.15*PI,.85*PI);c.stroke()
|
||||
c.beginPath();c.moveTo(181,86);c.lineTo(176,90);c.moveTo(184,89);c.lineTo(181,94);c.stroke()
|
||||
c.beginPath();c.moveTo(212,110);c.quadraticCurveTo(218,114,224,110);c.stroke();c.lineWidth=7
|
||||
bundle(k=>{const o=k*5-12;c.moveTo(184-o*.4,60+o*.6);c.bezierCurveTo(160-o*.8,64+o*.4,150+5*w-o*.9,96,140+7*w-o,136+o*.3)})
|
||||
c.save();c.translate(200,66);c.rotate(.5)
|
||||
c.fillStyle=HN;c.beginPath();c.moveTo(-11,0);c.lineTo(0,-54);c.lineTo(11,0);c.closePath();c.fill();c.stroke()
|
||||
c.lineWidth=4;for(const y of[-14,-28,-40])c.beginPath(),c.moveTo(-9-y*.2,y+4),c.lineTo(9+y*.2,y-4),c.stroke()
|
||||
c.restore();c.lineWidth=7
|
||||
const s=abs(sin(2*T*t+.6)),sx=236,sy=24
|
||||
if(s>.25){c.fillStyle=HN;c.lineWidth=4;c.beginPath();for(let k=0;k<8;k++){const r=k%2?6*s:20*s,a=k*PI/4-PI/2;c.lineTo(sx+cos(a)*r,sy+sin(a)*r)}c.closePath();c.fill();c.stroke()}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
// record player spinning a vinyl whose label has a little face, tonearm riding the grooves, notes floating up
|
||||
const{sin,cos,PI}=Math,T=2*PI
|
||||
export const frames=20,delay=80
|
||||
const BASE='#ffa94d',BD='#e8590c',REC='#343a40',GR='#5c636a',SH='#868e96',LAB='#ff6b6b',ARM='#dee2e6',HEAD='#ffd43b',NOTE=['#4dabf7','#b197fc']
|
||||
const note=(c,x,y,s,col)=>{
|
||||
c.save();c.translate(x,y);c.scale(s,s);c.fillStyle=col
|
||||
for(const[w,st]of[[9,'#111'],[3,col]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(5,4),c.lineTo(5,-24),c.lineTo(17,-18),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=4;c.beginPath();c.ellipse(0,5,8,6,-.4,0,T);c.fill();c.stroke();c.restore()
|
||||
}
|
||||
export default(c,t)=>{
|
||||
const cx=110,cy=150
|
||||
c.fillStyle=BASE;c.beginPath();c.roundRect(22,64,212,168,22);c.fill();c.stroke()
|
||||
c.fillStyle=BD;c.lineWidth=5;c.beginPath();c.roundRect(186,206,30,12,6);c.fill();c.stroke()
|
||||
c.fillStyle='#fff';c.beginPath();c.arc(202,184,10,0,T);c.fill();c.stroke();c.beginPath();c.moveTo(202,184);c.lineTo(202,176);c.stroke()
|
||||
c.lineWidth=7;c.fillStyle=REC;c.beginPath();c.arc(cx,cy,76,0,T);c.fill();c.stroke()
|
||||
c.strokeStyle=GR;c.lineWidth=2;for(const r of[66,58,50,42])c.beginPath(),c.arc(cx,cy,r,0,T),c.stroke()
|
||||
c.strokeStyle=SH;c.lineWidth=5;for(const[r,a0]of[[62,-2.5],[54,.65]])c.beginPath(),c.arc(cx,cy,r,a0,a0+.5),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
c.save();c.translate(cx,cy);c.rotate(T*t)
|
||||
c.fillStyle=LAB;c.lineWidth=5;c.beginPath();c.arc(0,0,28,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(d*10,-9,3.5,0,T),c.fill()
|
||||
c.lineWidth=3.5;c.beginPath();c.arc(0,8,7,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle='#ffc9c9';for(const d of[-1,1])c.beginPath(),c.ellipse(d*17,2,4,2.5,0,0,T),c.fill()
|
||||
c.restore()
|
||||
c.fillStyle=ARM;c.lineWidth=3;c.beginPath();c.arc(cx,cy,4,0,T);c.fill();c.stroke()
|
||||
const hx=166,hy=196
|
||||
for(const[w,st]of[[13,'#111'],[6,ARM]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(206,92),c.lineTo(208,160),c.lineTo(hx,hy),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=5
|
||||
c.save();c.translate(hx,hy);c.rotate(.75);c.fillStyle=HEAD;c.beginPath();c.roundRect(-9,-6,22,14,4);c.fill();c.stroke();c.restore()
|
||||
c.fillStyle=ARM;c.beginPath();c.roundRect(196,64,20,16,4);c.fill();c.stroke()
|
||||
c.lineWidth=7;c.beginPath();c.arc(206,92,14,0,T);c.fill();c.stroke()
|
||||
c.fillStyle='#868e96';c.beginPath();c.arc(206,92,5,0,T);c.fill()
|
||||
for(let k=0;k<2;k++){const p=(t+k/2)%1,s=p<.2?p*5:p<.8?1:(1-p)*5;note(c,108+(k?10:-12)+6*sin(p*T),112-p*94,s,NOTE[k])}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
// watering can with a face tips forward and sprinkles a droopy sprout in a pot, which perks up, then gets thirsty again
|
||||
const{sin,cos,PI,min,max}=Math,T=2*PI
|
||||
export const frames=24,delay=80
|
||||
const CAN='#4dabf7',CD='#1c7ed6',POT='#ff922b',PD='#e8590c',SOIL='#a9744f',LF='#69db7c',LD='#2f9e44',DROP='#a5d8ff',BL='#faa2c1'
|
||||
const sm=x=>x<0?0:x>1?1:x*x*(3-2*x)
|
||||
const sparkle=(c,x,y,s)=>{c.fillStyle='#fff9db';c.lineWidth=3.5;c.beginPath();c.moveTo(x,y-s);for(const[px,py,qx,qy]of[[s,0,s*.18,-s*.18],[0,s,s*.18,s*.18],[-s,0,-s*.18,s*.18],[0,-s,-s*.18,-s*.18]])c.quadraticCurveTo(x+qx,y+qy,x+px,y+py);c.fill();c.stroke()}
|
||||
export default(c,t)=>{
|
||||
const tip=sm((t-.04)/.14)-sm((t-.6)/.14),a=.5*tip,perk=sm((t-.34)/.2)-sm((t-.8)/.18)
|
||||
const PX=74,PY=112,rose=[PX+86*cos(a)+34*sin(a),PY+86*sin(a)-34*cos(a)]
|
||||
c.fillStyle=SOIL;c.beginPath();c.ellipse(190,190,38,7,0,0,T);c.fill();c.stroke()
|
||||
const tx=214-24*perk,ty=170-34*perk,qx=204-14*perk,qy=176-24*perk
|
||||
for(const[w,st]of[[11,'#111'],[5,LD]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.moveTo(190,190),c.quadraticCurveTo(qx,qy,tx,ty),c.stroke()
|
||||
c.strokeStyle='#111'
|
||||
for(const[up,dn]of[[3.78,2.2],[-.6,.9]]){
|
||||
const th=dn+(up-dn)*perk,x=tx+15*cos(th),y=ty+15*sin(th)
|
||||
c.fillStyle=LF;c.lineWidth=5;c.beginPath();c.ellipse(x,y,15,8,th,0,T);c.fill();c.stroke()
|
||||
c.lineWidth=2.5;c.beginPath();c.moveTo(tx,ty);c.lineTo(x+8*cos(th),y+8*sin(th));c.stroke()
|
||||
}
|
||||
if(perk>.7){const s=10*(perk-.7)/.3;sparkle(c,166,132,s);sparkle(c,226,142,s*.7)}
|
||||
c.lineWidth=7;c.fillStyle=POT;c.beginPath();c.moveTo(154,204);c.lineTo(226,204);c.lineTo(216,246);c.lineTo(164,246);c.closePath();c.fill();c.stroke()
|
||||
c.fillStyle=PD;c.beginPath();c.roundRect(146,188,88,18,6);c.fill();c.stroke()
|
||||
c.fillStyle='#111';for(const d of[-1,1])c.beginPath(),c.arc(190+d*13,222,4,0,T),c.fill()
|
||||
c.lineWidth=3.5;c.beginPath();if(perk>.5)c.arc(190,227,6,.15*PI,.85*PI);else c.moveTo(184,232),c.quadraticCurveTo(190,227,196,232);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(190+d*24,230,5,3,0,0,T),c.fill()
|
||||
if(t>.18&&t<.74)for(let j=0;j<12;j++){
|
||||
const s0=.18+j*.04,u=(t-s0)/.12;if(u<0||u>1||s0>.62)continue
|
||||
const off=((j*5)%3-1)*6,x=rose[0]+off+22*u,y=rose[1]+4+(188-rose[1]-4)*u
|
||||
c.fillStyle=DROP;c.lineWidth=3;c.beginPath();c.moveTo(x,y-7);c.quadraticCurveTo(x+5,y,x,y+3);c.quadraticCurveTo(x-5,y,x,y-7);c.fill();c.stroke()
|
||||
}
|
||||
c.save();c.translate(PX,PY);c.rotate(a);c.lineWidth=7
|
||||
for(const[w,st]of[[15,'#111'],[7,CD]])c.lineWidth=w,c.strokeStyle=st,c.beginPath(),c.arc(-18,-30,22,PI*1.05,PI*1.95),c.stroke()
|
||||
c.strokeStyle='#111';c.lineWidth=7
|
||||
c.fillStyle=CAN;c.beginPath();c.moveTo(30,4);c.lineTo(80,-30);c.lineTo(88,-20);c.lineTo(34,24);c.closePath();c.fill();c.stroke()
|
||||
c.save();c.translate(86,-32);c.rotate(-.6);c.fillStyle=CD;c.beginPath();c.roundRect(-6,-14,14,28,5);c.fill();c.stroke()
|
||||
c.fillStyle='#e7f5ff';for(const y of[-6,0,6])c.beginPath(),c.arc(8,y,1.8,0,T),c.fill();c.restore()
|
||||
c.fillStyle=CAN;c.beginPath();c.roundRect(-50,-32,86,72,16);c.fill();c.stroke()
|
||||
c.fillStyle=CD;c.beginPath();c.roundRect(-50,-32,86,14,[16,16,0,0]);c.fill();c.lineWidth=5;c.stroke()
|
||||
const happy=tip>.5
|
||||
c.fillStyle='#111';c.lineWidth=4
|
||||
if(happy)for(const d of[-1,1])c.beginPath(),c.arc(-7+d*14,4,5,PI*1.1,PI*1.9),c.stroke()
|
||||
else for(const d of[-1,1])c.beginPath(),c.arc(-7+d*14,2,4.5,0,T),c.fill()
|
||||
c.beginPath();c.arc(-7,12,7,.15*PI,.85*PI);c.stroke()
|
||||
c.fillStyle=BL;for(const d of[-1,1])c.beginPath(),c.ellipse(-7+d*26,16,5,3,0,0,T),c.fill()
|
||||
c.restore()
|
||||
}
|
||||
Reference in New Issue
Block a user