I am pretty confused regarding the following behavior. The D3v3 forced graph below shows 4 nodes, with at least one link to another node. I dont know why, but the distance between the nodes is broken as I got more than 3 nodes. Even if distance and charge are set.
var width = window.innerWidth,
height = window.innerHeight;
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.call(d3.behavior.zoom().on("zoom", function() {
svg.attr("transform", "translate(" + d3.event.translate + ")" + "scale(" + d3.event.scale + ")")
}))
.append("g")
var defs = svg.append("defs")
const arc = d3.svg.arc()
.innerRadius(80 + 10)
.outerRadius(80 + 10)
.startAngle(-Math.PI)
.endAngle(Math.PI)
defs.append("path")
.attr("id", "curvedLabelPath")
.attr("d", arc())
////////////////////////
// outer force layout
var outerData = {
"nodes": [
{ "id": "A" },
{ "id": "B" },
{ "id": "C" },
{ "id": "D" }
],
"links": [
{ "source": 0, "target": 1},
{ "source": 1, "target": 2},
{ "source": 2, "target": 0},
{ "source": 3, "target": 0}
]
};
var outerLayout = d3.layout.force()
.size([width, height])
.charge(-1000)
.gravity(0.85)
.distance(500)
.links(outerData.links)
.nodes(outerData.nodes)
.start();
var outerLinks = svg.selectAll("g")
.data(outerData.links)
.enter().append("g")
.attr("cursor", "pointer")
//.attr("class", "g.outerLink")
var outerLine = outerLinks
.append("path")
.attr("id", function (_, i) {
return "path" + i
})
.attr("stroke", "black")
.attr("opacity", 0.75)
.attr("stroke-width", 3)
.attr("fill", "transparent")
.attr("cursor", "default")
var outerNodes = svg.selectAll("g.outer")
.data(outerData.nodes, function (d) { return d.id; })
.enter()
.append("g")
.attr("class", "outer")
.attr("id", function (d) { return d.id; })
.call(outerLayout.drag()
.on("dragstart", function () {
d3.event.sourceEvent.stopPropagation();
})
)
.attr("cursor", "pointer")
outerNodes
.append("circle")
.style("fill", "whitesmoke")
.style("stroke", "black")
.style("stroke-width", 3)
.attr("r", 80);
outerNodes
.append("text")
.append("textPath")
.attr("href", "#curvedLabelPath")
.attr("text-anchor", "middle")
.attr("startOffset", "25%")
.attr("font-size", "30px")
.attr("cursor", "pointer")
.text(function (d) {
return d.id
})
outerLayout
.on("tick", function() {
outerLine.attr("d", function (d) {
var dx = (d.target.x - d.source.x),
dy = (d.target.y - d.source.y),
dr = Math.sqrt(dx * dx + dy * dy);
return "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y;
});
outerNodes
.attr("transform", function (d) { return "translate(" + d.x + "," + d.y + ")"; });
})
body {
background: whitesmoke,ยด;
overflow: hidden;
margin: 0px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>D3v3 forces</title>
<!-- d3.js framework -->
<script src="https://d3js.org/d3.v3.js"></script>
</head>
</html>
I am aware force setup is different in v4 and higher, still regarding my opinion some features are handled better in v3. I would be glad if an D3 expert could either help or explain those behaviour.