带有传单和 D3.js [问题] 的气泡图:气泡重叠

Bubble Map with leaflet and D3.js [problem] : bubbles overlapping

我这里有一张带有虚拟数据的基本地图。基本上是气泡图。
问题是我有多个点(例如:20)具有完全相同的 GPS 坐标。 下图是我的带有虚拟数据的 csv,在此基本示例中,蓝色突出显示重叠点。那是因为很多公司都有相同的城市gps坐标。

这是一个 fiddle,其中包含我正在处理的代码:
https://jsfiddle.net/MathiasLauber/bckg8es4/45/ 后来研究了很多,发现d3.js加上这个力模拟功能,可以避免点碰撞。

// Avoiding bubbles overlapping
    var simulationforce = d3.forceSimulation(data)

      .force('x', d3.forceX().x(d => xScale(d.longitude)))
      .force('y', d3.forceY().y(d => yScale(d.latitude)))
      .force('collide', d3.forceCollide().radius(function(d) {
        return d.radius + 10
      }))
  simulationforce
    .nodes(cities)
    .on("tick", function(d){
      node
       .attr("cx", function(d) { return projection.latLngToLayerPoint([d.latitude, d.longitude]).x;                 })
        .attr("cy", function(d) {return projection.latLngToLayerPoint([d.latitude, d.longitude]).y;                     })
    });

问题是我无法进行强制布局,而且我的点仍然在彼此之上。 (第 188-200 行在 fiddle).

如果您有任何提示、建议,或者如果您发现我的代码中存在基本错误,请告诉我 =D

一堆代码接近我想要实现的目标
https://d3-graph-gallery.com/graph/circularpacking_group.html
https://jsbin.com/taqewaw/edit?html,output

有3个问题:

  1. 为了将圆定位在其原始位置附近,需要在传递给 simulation.nodes() 调用的数据中指定 xy 初始位置。
  2. 进行力模拟时,需要在on tick回调中提供要模拟的选择(参见on('tick')回调函数中的node)。
  3. 模拟需要使用之前的 d.xd.y 模拟计算的值

相关代码片段如下

// 1. Add x and y (cx, cy) to each row (circle) in data 
const citiesWithCenter = cities.map(c => ({
  ...c,
  x: projection.latLngToLayerPoint([c.latitude, c.longitude]).x,
  y: projection.latLngToLayerPoint([c.latitude, c.longitude]).y,
}))
// citiesWithCenter will be passed to selectAll('circle').data()
// 2. node selection you forgot
 const node = selection
        .selectAll('circle')
        .data(citiesWithcenter)
        .enter()
        .append('circle')
...
// let used in simulation
 simulationforce.nodes(citiesWithcenter).on('tick', function (d) {
   node
     .attr('cx', function (d) {
            // 3. use previously computed x value 
            // on the first tick run, the values in citiesWithCenter is used
            return d.x
          })
     .attr('cy', function (d) {
            // 3. use previously computed y value 
            // on the first tick run, the values in citiesWithCenter is used
            return d.y
          })
})

完整的工作演示在这里:https://jsfiddle.net/b2Lhfuw5/