如何通过半径大小将节点定位在中心?



我想按圆的大小在力导向图中居中节点:我们希望最大的圆居中,下一个最大的圆围绕它。

以下是JSFiddle:https://jsfiddle.net/5zrxgteh/1/

以下是模拟和即时报价函数:

var simulation = d3.forceSimulation()
.force("center", d3.forceCenter().x(width / 2).y(height / 2))
.force("charge", d3.forceManyBody().strength(5))
.force("collide", d3.forceCollide().strength(1).radius(function (d) {
return rScale(d.value * 1.2);
}).iterations(3));
simulation
.nodes(data)
.on("tick", function (d) {
elemEnter.selectAll(".pulse")
.attr("cx", function (d) {
return d.x = Math.max(50, Math.min(width - 50, d.x));
})
.attr("cy", function (d) {
return d.y = Math.max(50, Math.min(height - 50, d.y));
});
elemEnter.selectAll(".circle")
.attr("cx", function (d) {
return d.x = Math.max(50, Math.min(width - 50, d.x));
})
.attr("cy", function (d) {
return d.y = Math.max(50, Math.min(height - 50, d.y));
});
elemEnter.selectAll("text")
.attr("x", function (d) {
return d.x = Math.max(50, Math.min(width - 50, d.x));
})
.attr("y", function (d) {
return d.y = Math.max(50, Math.min(height - 50, d.y));
});
});

如果你停下来思考你想要的东西在数学和视觉上都很复杂,因为如果最大的圆紧挨着中心,并且到中心的距离与圆的直径成正比,那么你在中心旁边会有很多空白,模拟不会很好地处理它。

然而,只是为了尝试,这是一个可能的解决方案:放弃d3.forceCenter,改用forceXforceY,根据圆圈的大小调整它们的强度。

为此,我们首先设置了一个比例:

var strengthScale = d3.scalePow()
.exponent(2)
.range([0, 1])
.domain([0, d3.max(data, function(d) {
return d.value;
})]);

然后,我们更改模拟:

var simulation = d3.forceSimulation()
.force("x", d3.forceX(width / 2).strength(function(d) {
return strengthScale(d.value);
}))
.force("y", d3.forceY(height / 2).strength(function(d) {
return strengthScale(d.value);
}))
.force("charge", d3.forceManyBody().strength(5))
.force("collide", d3.forceCollide().strength(1).radius(function(d) {
return rScale(d.value * 1.2);
}).iterations(30));

下面是生成的 JSFiddle: https://jsfiddle.net/mea9nygb/2/

最新更新