Published unlisted
Edited
Sep 7, 2022
Insert cell
Insert cell
Insert cell
svg = {
const svg = d3.select(DOM.svg(width, height));
const graph = d3
.csvParse(myData, types)
.map((d) => ({ ...d, t: 0 }))
.sort((a, b) => b.size - a.size);
let hovered;

simulation
.nodes(graph)
.force("collide", collide)
.on("tick", () => {
node
.attr("r", (d) => {
d.t = (d===hovered) ? (1-(1-d.t)*0.96) : (d.t*0.96);
d.r = (d.r>=50) ? (d.r) : ((1-d.t)*d.radius + d.t*Math.max(d.radius*1.2, 50));
return d.r;
})
.attr("cx", (d) => d.x)
.attr("cy", (d) => d.y);
collide
.radius((d) => d.radius + nodePadding); //here set node radius based on d.r and d.t values

path
.attr("d", d => createCirclePath(d.x, d.y, d.r))

})
.alpha(1)
.restart();

const node = svg
.append("g")
.selectAll("circle")
.data(graph)
.join("circle")

const path = svg
.append("g")
.selectAll("path")
.data(graph)
.join("path")
.attr('id', d => d.country)
.style('pointer-events', 'none')
const text = svg
.append('g')
.selectAll('text')
.data(graph)
.join('text')
.attr("font", '12px sans-serif')
.style('pointer-events', 'none')
.append("textPath")
.attr("startOffset","50%")
.attr('href', d => `#${d.country}`)
.text(d => d.country)
.attr('text-anchor', 'middle');

node
.on("pointerenter", (event, d) => {
hovered = d;
simulation.tick();
})
.on("pointerout", (event, d) => {
hovered = null;
simulation.tick();
});

node
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));

return svg.node();
}
Insert cell
createCirclePath = (x, y, r) => `
M ${x} ${y + r}
a ${r},${r} 0 1,1 0, ${r * -2}
a ${r},${r} 0 1,1 0, ${r * 2}
`
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