Published
Edited
May 3, 2020
5 forks
12 stars
Insert cell
Insert cell
Insert cell
chart = {
replay;
const svg = d3.select(DOM.svg(width, height));
const data = d3.range(10).map((d, i) => (
{
width: 120,
height: 40,
x: Math.random() * width,
y: Math. random() * height
}));
const nodes = data;
const node = svg.append("g")
.selectAll("rect")
.data(nodes)
.join("rect")
.attr("x", d => d.x - d.width/2)
.attr("y", d => d.y - d.height/2)
.attr('width', d => d.width)
.attr('height', d => d.height)
.style('fill', (d, i) => color(i % 10));
const simulation = d3.forceSimulation(nodes)
.force("x", d3.forceX(width / 2).strength(0.05))
.force("y", d3.forceY(height / 2).strength(0.05))
.force("collide", forceCollide());
simulation.on('tick', () => {
node.attr("x", d => d.x - d.width/2)
.attr("y", d => d.y - d.height/2);
});

invalidation.then(() => simulation.stop());
return svg.node();
}
Insert cell
color = d3.scaleOrdinal(d3.range(10), d3.schemeCategory10);
Insert cell
function forceCollide() {
let nodes;

function force(alpha) {
const quad = d3.quadtree(nodes, d => d.x, d => d.y);
for (const d of nodes) {
quad.visit((q, x1, y1, x2, y2) => {
let updated = false;
if(q.data && q.data !== d){
let x = d.x - q.data.x,
y = d.y - q.data.y,
xSpacing = padding + (q.data.width + d.width) / 2,
ySpacing = padding + (q.data.height + d.height) / 2,
absX = Math.abs(x),
absY = Math.abs(y),
l,
lx,
ly;

if (absX < xSpacing && absY < ySpacing) {
l = Math.sqrt(x * x + y * y);

lx = (absX - xSpacing) / l;
ly = (absY - ySpacing) / l;

// the one that's barely within the bounds probably triggered the collision
if (Math.abs(lx) > Math.abs(ly)) {
lx = 0;
} else {
ly = 0;
}
d.x -= x *= lx;
d.y -= y *= ly;
q.data.x += x;
q.data.y += y;

updated = true;
}
}
return updated;
});
}
}

force.initialize = _ => nodes = _;

return force;
}


Insert cell
d3 = require("d3@5");
Insert cell
width = 960
Insert cell
height = 500
Insert cell
padding = 5
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