chart = {
const links = data.links.map((d) => ({ ...d }));
const nodes = data.nodes.map((d) => ({ ...d }));
const height = 600;
const width = 900;
const linkForce = d3
.forceLink(links)
.id((d) => d.id)
.distance(80)
.strength(0.1);
const simulation = d3
.forceSimulation(nodes)
.stop()
.force("link", linkForce)
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2))
.alphaTarget(0.3);
const handleNodeDrag = d3
.drag()
.on("start", (event) => {
if (!event.active) {
simulation.alphaTarget(0.3);
}
event.subject.fx = event.subject.x;
event.subject.fy = event.subject.y;
})
.on("drag", (event) => {
event.subject.fx = event.x;
event.subject.fy = event.y;
})
.on("end", (event) => {
if (!event.active) {
simulation.alphaTarget(0);
}
event.subject.fx = null;
event.subject.fy = null;
});
const handleNodeClick = (event, d) => {
event.preventDefault();
d.selected = !d.selected;
};
const container = d3
.create("div")
.attr("class", "container")
.style("height", `${height}px`)
.style("width", `${width}px`);
const graphZoom = d3.zoom().on("zoom", (event) => {
const { x, y, k } = event.transform;
graph.style("transform", `translate(${x}px, ${y}px) scale(${k})`);
});
const graph = container.append("div").attr("class", "graph").call(graphZoom);
const items = graph
.selectAll()
.data(nodes)
.join("div")
.attr("class", "node")
.on("click", handleNodeClick)
.classed("selected", (d) => d.selected)
.text((d) => d.id)
.call(handleNodeDrag);
const tick = () => {
simulation.tick();
items.style("transform", (d) => `translate3d(${d.x}px, ${d.y}px, 0)`);
if (simulation.alpha() > 0) {
window.requestAnimationFrame(() => tick());
}
};
tick();
invalidation.then(() => simulation.stop());
return container.node();
}