There is an updated version of this gist. The blue node is a parent one, while orange are children. Basically, the task is to attract children to parent by adding links.
That's the outcome, I'm looking for, however sometimes children could be stopped and stuck by another green dots, like this
And that's really annoying. I'm not sure, but there's probably something wrong with collisions.
Any ideas?
var graph;
var currentLinks = 1;
// svg and sizing
var svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory10);
var link = svg.append("g").selectAll(".link"),
node = svg.append("g").selectAll(".node");
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody().strength(function(d) { return 50;}))
.force("collide", d3.forceCollide().radius(d => 10 + 10))
.force("center", d3.forceCenter(width / 2, height / 2));
d3.select("#switch-btn").on("click", function() {
currentLinks++;
if(currentLinks > 5) { currentLinks = 1}
update();
});
d3.select("#reset-btn").on("click", function() {
location.reload();
});
var graph = {
"nodes": [
{ "id": "0", "group": "2" },
{ "id": "1", "group": "3" },
{ "id": "2", "group": "3" },
{ "id": "3", "group": "1" },
{ "id": "4", "group": "1" },
{ "id": "5", "group": "3" },
{ "id": "6", "group": "3" },
{ "id": "7", "group": "1" },
{ "id": "8", "group": "1" },
{ "id": "9", "group": "1" },
{ "id": "10", "group": "1" },
{ "id": "11", "group": "1" },
{ "id": "12", "group": "1" },
{ "id": "13", "group": "1" },
{ "id": "14", "group": "1" },
{ "id": "15", "group": "1" },
{ "id": "16", "group": "1" },
{ "id": "17", "group": "1" }
],
"links1": [
{ "source": "0", "target": "0", "id": "0"},
{ "source": "1", "target": "1", "id": "1"},
{ "source": "2", "target": "2", "id": "2"},
{ "source": "3", "target": "3", "id": "3"},
{ "source": "4", "target": "4", "id": "4"},
{ "source": "5", "target": "5", "id": "5"},
{ "source": "6", "target": "6", "id": "6"},
{ "source": "7", "target": "7", "id": "7"},
{ "source": "8", "target": "8", "id": "8"},
{ "source": "9", "target": "9", "id": "9"},
{ "source": "10", "target": "10", "id": "10"},
{ "source": "11", "target": "11", "id": "11"},
{ "source": "12", "target": "12", "id": "12"},
{ "source": "13", "target": "13", "id": "13"},
{ "source": "14", "target": "14", "id": "14"},
{ "source": "15", "target": "15", "id": "15"},
{ "source": "16", "target": "16", "id": "16"},
{ "source": "17", "target": "17", "id": "17"}
],
"links2": [
{ "source": "0", "target": "5", "id": "0"}
],
"links3": [
{ "source": "0", "target": "5", "id": "0"},
{ "source": "0", "target": "2", "id": "0"}
],
"links4": [
{ "source": "0", "target": "5", "id": "0"},
{ "source": "0", "target": "2", "id": "0"},
{ "source": "0", "target": "6", "id": "0"}
],
"links5": [
{ "source": "0", "target": "5", "id": "0"},
{ "source": "0", "target": "2", "id": "0"},
{ "source": "0", "target": "6", "id": "0"},
{ "source": "0", "target": "1", "id": "0"}
]
};
update();
function reset() {
link = svg.append("g").selectAll(".link"),
node = svg.append("g").selectAll(".node");
simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody().strength(function(d) { return 50;}))
.force("collide", d3.forceCollide().radius(d => 10 + 10))
.force("center", d3.forceCenter(width / 2, height / 2));
update();
}
function update() {
link = link.data(graph["links" + currentLinks]);
// Remove old links
link.exit().remove();
// Create new links as needed.
link = link.enter().append("line")
.attr("class", "link")
.merge(link);
node = node.data(graph.nodes);
node.exit().remove();
node = node.enter().append("circle")
.attr("class", "node")
.attr("r", 10)
.attr("fill", function(d) {return color(d.group);})
.merge(node);
simulation.nodes(graph.nodes).on("tick", ticked);
simulation.force("link").links(graph["links" + currentLinks]);
simulation.alphaTarget(.3).restart();
}
function ticked() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
}
.buttons {
position: absolute;
top: 1em;
left: 1em;
}
.node {
stroke: white;
stroke-width: 2px;
}
.link {
stroke: gray;
stroke-width: 2px;
}
<div class="buttons">
<button type="button" id="switch-btn">update bubbles</button>
<button type="button" id="reset-btn">reset</button>
</div>
<svg width="500" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

