chart = {
const svg = d3.create("svg")
.attr("viewBox", [-width / 2, -height / 2, width, height]);
let simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id).distance(fLinkDistance).strength(fLinkStrength))
.force("r", d3.forceRadial().radius(d => d.r).strength(fRadialStrength))
.force("charge", d3.forceManyBody().strength(fAttraction))
.force("collide", d3.forceCollide().radius(fCollisionRadius).strength(fCollisionStrength).iterations(1))
.on("tick", ticked)
let link = svg.append("g")
.selectAll("line")
.data(links)
.join("line")
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y)
.attr("stroke-dasharray", "0 5")
.attr("stroke-linecap", "round")
.attr("stroke-width", 4)
.attr("stroke", d => d.source.color)
let node = svg.append("g")
.selectAll("circle")
.data(nodes)
.join("circle")
.attr("cx", d => d.x)
.attr("cy", d => d.y)
.attr("r", 20)
.attr("stroke-width", "2px")
.attr("stroke", "#000")
.attr('cursor', 'pointer')
.style("fill", d => d.color)
.on("click", (e, d) => addNodes(d))
function ticked() {
node = node
.attr("cx", d => d.x)
.attr("cy", d => d.y)
link = 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)
}
function addNodes(parent) {
const { color, r, id } = parent;
Array.from({length: nodesToAdd}, () => {
const newId = uuid();
nodes.push({ id: newId, color, r: parent.r + 300 });
links.push({ source: id, target: newId });
})
simulation.nodes(nodes).on("tick", null)
simulation.alpha(1)
while(simulation.alpha() > 0.3) {
simulation.tick()
}
simulation.nodes(nodes).on("tick", ticked)
node = node
.data(nodes)
.join(enter => enter.append("circle"))
.attr("r", 20)
.attr("stroke-width", "2px")
.attr("stroke", "#000")
.attr('cursor', 'pointer')
.style("fill", d => d.color)
.on("click", (e, d) => addNodes(d))
link = link
.data(links)
.join("line")
.attr("x1", d => d.source.x)
.attr("y1", d => d.source.y)
.attr("x2", d => d.target.x)
.attr("y2", d => d.target.y)
.attr("stroke-dasharray", "0 5")
.attr("stroke-linecap", "round")
.attr("stroke-width", 4)
.attr("stroke", d => d.source.color)
simulation.alpha(0.3).restart();
}
return svg.node();
}