Published
Edited
Nov 25, 2020
2 forks
5 stars
Insert cell
Insert cell
Insert cell
Insert cell
seed = Date.now()
Insert cell
noiseScale = 350
Insert cell
svg`<svg width="${w}" height="${h}">

${throttle(
svg`<g transform="translate(${w/2}, ${h/2}) scale(1.1) translate(-${w/2}, -${h/2})">`,
polygons.map((p, i) => () => svg`<g>
${Polygon.fromPath(`M ${p.segments[0].center.x}, ${p.segments[0].center.y} ${p.segments.map((seg, i, arr) => `C ${seg.b.x} ${seg.b.y} ${seg.b.x} ${seg.b.y} ${arr[(i + 1) % arr.length].center.x} ${arr[(i + 1) % arr.length].center.y}`).join(' ')} Z`).getHatches((simplex.noise3D(p.center.x/noiseScale, p.center.y/noiseScale, seed) * .5 + .5) * TAU * 2, map(simplex.noise3D(p.center.x/noiseScale, p.center.y/noiseScale, seed) * .5 + .5, 0, 1, 2, 10)).map(seg => `<line
stroke="black"
x1="${seg.a.x}"
y1="${seg.a.y}"
x2="${seg.b.x}"
y2="${seg.b.y}"
/>`)}
<path
fill="none"
stroke="black"
stroke-width="1"
d="M ${p.segments[0].center.x}, ${p.segments[0].center.y} ${p.segments.map((seg, i, arr) => `C ${seg.b.x} ${seg.b.y} ${seg.b.x} ${seg.b.y} ${arr[(i + 1) % arr.length].center.x} ${arr[(i + 1) % arr.length].center.y}`).join(' ')} Z"
/></g>`))})}
</g>
</svg>`
Insert cell
function throttle(parent, callbacks) {
const delay = 50;
const queue = callbacks.slice();
let i = 0;
invalidation.then(() => i = queue.length);
process();
return parent;
function process() {
const start = Date.now();
while(i < queue.length) {
const n = queue[i++]();
parent.appendChild(n);
if(i+1 < queue.length && Date.now() - start >= delay) {
setTimeout(process, 0);
return;
}
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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