graph = {
const height = 600;
const root = d3.hierarchy(data);
const links = root.links();
const nodes = root.descendants();
const simulation = d3
.forceSimulation(nodes)
.force(
"link",
d3
.forceLink(links)
.id((d) => d.id)
.distance(70)
)
.force("charge", d3.forceManyBody().strength(-200))
.force(
"collide",
d3.forceCollide().radius(function (d) {
return 64;
})
)
.force("center", d3.forceCenter(width / 2, height / 2));
const svg = d3.select(DOM.svg(width, height));
const link = svg
.append("g")
.attr("stroke", "#999")
.attr("stroke-opacity", 0.6)
.selectAll("line")
.data(links)
.join("line");
const node = svg
.append("g")
.attr("fill", "currentColor")
.attr("stroke-linecap", "round")
.attr("stroke-linejoin", "round")
.selectAll("g")
.data(nodes)
.join("g")
.call(drag(simulation));
node
.append("circle")
.attr("stroke", "white")
.attr("stroke-width", 1.5)
.attr("r", 4);
node
.append("svg:a")
.attr("xlink:href", function (d) {
return "https://en.wikipedia.org/?curid=" + d.data.pageid;
})
.attr("target", "_blank")
.append("text")
.attr("x", 8)
.attr("y", "0.31em")
.text((d) => d.data.name)
.clone(true)
.lower()
.attr("fill", "none")
.attr("stroke", "white")
.attr("stroke-width", 3);
simulation.on("tick", () => {
link
.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
node.attr("transform", (d) => `translate(${d.x},${d.y})`);
});
invalidation.then(() => simulation.stop());
return svg.node();
}