svg = {
const svg = d3.select(this || DOM.svg(svgSize, svgSize));
const g = svg.select("g.top").empty() ?
svg.append("g")
.attr("class", "top")
.attr("transform", `translate(${svgSize / 2},${svgSize / 2})`)
.attr("stroke", "currentColor")
.attr("stroke-width", 1.5) :
svg.select("g");
const allNodes = g.selectAll(".node").data(nodes, d => d.name);
const t = d3.transition().duration(tickPeriod * .8);
const nodesExiting = allNodes.exit();
nodesExiting.transition(t).remove();
nodesExiting.selectAll("circle")
.attr("class", "exit")
.style("fill", "red")
.transition(t)
.attr("r", 1e-6);
nodesExiting.selectAll("text")
.attr("class", "exit")
.style("fill", "black")
.transition(t)
.attr("font-size", 6);
const updatingCircles = allNodes.selectAll("circle").data(nodes, d => d.name);
updatingCircles.transition(t)
.style("fill", "steelblue")
.attr("r", d => d.size);
const updatingText = allNodes.selectAll("text").data(nodes, d => d.name);
updatingText.transition(t)
.style("fill", "white");
const nodesEntering = allNodes.enter().append("g")
.attr("class", "node");
nodesEntering.append("circle")
.style("fill", "lightgreen")
.attr("r", d => (d.size + 5))
.attr("cx", d => d.initX).attr("cy", d => d.initY);
nodesEntering.append("text")
.attr("font-size", 22)
.style("fill", "blue")
.style("stroke", "none")
.attr("text-anchor", "middle")
.attr("dominant-baseline", "central")
.text(d => d.name)
.attr("x", d => d.initX).attr("y", d => d.initY);
simulation
.force("collide",
d3.forceCollide()
.strength(1)
.radius(d => (d.size + 25))
.iterations(5))
.on("tick", ticked);
function ticked() {
const allNodes = d3.select("g.top").selectAll(".node").data(nodes);
allNodes.selectAll("circle").attr("cx", d => d.x).attr("cy", d => d.y);
allNodes.selectAll("text") .attr("x", d => d.x).attr("y", d=> d.y);
}
return svg.node();
}