function* animation(options = {}) {
const {
size = 600,
radius = 1,
background = 'white',
color = 'black',
steps = 10,
strokeWidth = 10,
dashes = 10,
duration = 5000,
} = options;
const ease = t => Math.cos(t*Math.PI*2) * .5 + .5,
circles = Array.from(
{length: steps},
(_, i) => svg`<circle r=${size/2*radius*i/steps}>`
),
view = svg`
<svg viewBox="${-size/2} ${-size/2} ${size} ${size}"
width=${size} preserveAspectRatio="xMidYMid meet" style="max-width:100%">
<rect x=${-size/2} y=${-size/2} width=${size} height=${size} fill=${background} />
<g transform="rotate(90)" fill=none stroke=${color} stroke-linecap=round>
${circles}`;
const update = tGlobal => {
for(const [i, c] of circles.entries()) {
const t = -.001 + ease(i/circles.length + tGlobal),
segment = c.getTotalLength() / dashes,
dash = segment * (1-t),
gap = segment * t;
c.setAttribute('stroke-dasharray', `${dash},${gap}`);
c.setAttribute('stroke-dashoffset', -gap / 2);
c.setAttribute('stroke-width', 2 + t * strokeWidth);
}
};
yield view;
while(true) {
update(Date.now() / duration % 1);
yield view;
}
}