force_graph = {
let w = 800;
let h = 700;
let s = 0.05;
let chart = d3
.create("svg")
.attr("viewBox", [0, 0, w, h])
.style("max-width", "800px");
let nodes = connections.nodes;
let links = connections.edges;
let link = chart
.append("g")
.attr("class", "links")
.selectAll("line")
.data(links)
.join("line")
.attr("source", (d) => d.source)
.attr("target", (d) => d.target)
.attr("stroke-width", 1)
.attr("stroke", "black");
let node = chart.append("g").attr("class", "nodes");
node
.selectAll("g")
.data(nodes)
.join(function (enter) {
let g = enter
.append("g")
.attr("class", "node-container")
.attr("transform", `scale(${s})`);
g.append("circle")
.attr("r", 500)
.attr("cx", `${0.5 * w}`)
.attr("cy", `${0.5 * h}`)
.attr("fill", "lightgray")
.attr("stroke", "black")
.attr("fill-opacity", 0.4)
.attr("stroke-opacity", 0.2)
.attr("stroke-width", 40);
g.append((d) => svg`${images.get(icon_to_image.get(d.label))}`);
});
let simulation = d3
.forceSimulation()
.force("charge", d3.forceManyBody().strength(-300))
.force("collide", d3.forceCollide(30))
.force("center", d3.forceCenter(w / 2, h / 2))
.force(
"link",
d3.forceLink().id((d) => d.id)
);
simulation.nodes(nodes).on("tick", tick);
simulation.force("link").links(links);
return chart.node();
function tick() {
link
.attr("x1", function (d) {
return d.source.x + (s * w) / 2;
})
.attr("y1", function (d) {
return d.source.y + (s * h) / 2;
})
.attr("x2", function (d) {
return d.target.x + (s * w) / 2;
})
.attr("y2", function (d) {
return d.target.y + (s * h) / 2;
});
node
.selectAll("g.node-container")
.attr("transform", (d) => `translate(${d.x} ${d.y}) scale(${s})`);
}
}