forceLayout = {
const margin = {
top: 40,
bottom: 10,
left: 20,
right: 20
};
const width = 700 - margin.left - margin.right;
const height = 500 - margin.top - margin.bottom;
const svg = d3
.create("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
const g = svg
.append("g")
.attr("transform", `translate(${margin.left}, ${margin.top})`);
const simulation = d3
.forceSimulation()
.force(
"link",
d3.forceLink().id((d) => d.id)
)
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
const color = d3.scaleOrdinal(d3.schemeCategory10);
const link = g
.selectAll(".link")
.data(miserables.links)
.join((enter) => enter.append("line").attr("class", "link"));
const node = g
.selectAll(".node")
.data(miserables.nodes)
.join((enter) => {
const node_enter = enter
.append("circle")
.attr("class", "node")
.attr("r", 5);
node_enter.append("title").text((d) => d.id);
return node_enter;
});
node.style("fill", (d) => color(d.group));
simulation.nodes(miserables.nodes).force("link").links(miserables.links);
simulation.on("tick", (e) => {
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("cx", (d) => d.x).attr("cy", (d) => d.y);
});
return svg.node();
}