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