我想通过圆的大小将力指向图表中的节点居中:我们希望最大的圆居中,周围的第二大圆为中心。
这里是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
并改用forceX
和forceY
,根据圆的大小调整其强度。
为此,我们首先设置一个比例尺:
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/