{
let a = 0.2;
let circles = layout(a);
const context = DOM.context2d(width, height);
const timer = d3.timer(() => {
context.save();
context.clearRect(0, 0, width, height);
context.translate(width / 2, height / 2);
context.rotate(Math.sin(Date.now() / 10000));
context.translate(-width / 2, -height / 2);
context.beginPath();
for (let i = 0; i < n; ++i) {
let move = true;
d3.pairs(circles, (
{x: x1, y: y1, r: r1, a: a1},
{x: x2, y: y2, r: r2, a: a2}
) => {
const ai = (i * 2) / n * Math.PI;
context[move ? (move = false, "moveTo") : "lineTo"](...point(x1, y1, r1, a1 + ai));
context.lineTo(...point(x2, y2, r2, a2 + ai));
});
d3.pairs(circles.slice().reverse(), (
{x: x1, y: y1, r: r1, a: a1},
{x: x2, y: y2, r: r2, a: a2}
) => {
const ai = (i * 2 + 1) / n * Math.PI;
context.lineTo(...point(x1, y1, r1, a1 + ai));
context.lineTo(...point(x2, y2, r2, a2 + ai));
});
context.closePath();
}
context.fill();
context.restore();
});
const interval = d3.interval(() => {
d3.transition().duration(4000).tween("circles", () => {
const i = d3.interpolate(circles, layout(a = -a));
return t => circles = i(t);
});
}, 5000, d3.now() - 4000);
invalidation.then(() => timer.stop());
invalidation.then(() => interval.stop());
return context.canvas;
}