Published
Edited
Feb 19, 2019
2 stars
Insert cell
Insert cell
fullscreen = {
const button = html`<button>Fullscreen`;
button.onclick = () => button.parentElement.nextElementSibling.requestFullscreen();
return button;
}
Insert cell
canvas = {
const height = Math.ceil(width * screen.height / screen.width);
const n = width*height/1000;
const margin = 60;
const context = DOM.context2d(width, height);
const particles = Array.from({length: n}, () => [Math.random() * width, Math.random() * height, 0, 0]);
context.canvas.style.background = "#000";
let h = 1;
context.filter = 'blur(2px)';

context.fillStyle = "rgba(0,0,0,.01)";
while (true) {
h = h >= 360 ? 1 : h+1;
context.strokeStyle = "hsla("+h+",70%,10%,1)";
const delaunay = new d3.Delaunay.from(particles);
const voronoi = delaunay.voronoi([0, 0, width, height]);
context.save();
context.globalCompositeOperation = 'source-atop';
context.rect(0, 0, width, height);
context.fill();
context.globalCompositeOperation = 'screen';
// delaunay.renderPoints(context);
context.beginPath();
voronoi.render(context);
context.stroke();


yield context.canvas;
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] += width*height/10000000 * (Math.random() - 0.5) - 0.01 * p[2];
p[3] += width*height/10000000 * (Math.random() - 0.5) - 0.01 * p[3];
}
}
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more