canvas = {
const n = 200;
const height = Math.ceil(width * screen.height / screen.width);
const margin = 60;
const svg = htl.svg`<svg width=${width} height=${height} style="background: white; display: block;">`;
const pointsPath = svg.appendChild(htl.svg`<path fill="currentColor">`);
const meshPath = svg.appendChild(htl.svg`<path stroke="red" fill="none">`);
const particles = Array.from({length: n}, () => [Math.random() * width, Math.random() * height, 0, 0]);
while (true) {
const delaunay = d3.Delaunay.from(particles);
const voronoi = delaunay.voronoi([0, 0, width, height]);
pointsPath.setAttribute("d", delaunay.renderPoints());
meshPath.setAttribute("d", voronoi.render());
yield svg;
for (const p of particles) {
p[0] += p[2];
p[1] += p[3];
if (p[0] < -margin) p[0] += width + margin * 2;
else if (p[0] > width + margin) p[0] -= width + margin * 2;
if (p[1] < -margin) p[1] += height + margin * 2;
else if (p[1] > height + margin) p[1] -= height + margin * 2;
p[2] += 0.2 * (Math.random() - 0.5) - 0.01 * p[2];
p[3] += 0.2 * (Math.random() - 0.5) - 0.01 * p[3];
}
}
}