Если вы перестанете думать, что то, что вы хотите, сложно, как математически, так и визуально, потому что, если самые большие круги находятся рядом с центром, а расстояние до центра пропорционально диаметру круга, то у вас будет многопустые пробелы рядом с центром, и симуляция с этим не справится.
Однако, только для попытки, это возможное решение: рвите 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/