如何使 D3 碰撞力仅应用于 X



我想在 D3 中使用碰撞力来防止力布局中节点之间的重叠,但我的 y 轴是基于时间的。我只想在节点的 x 位置上使用力。

我尝试将碰撞力与力 Y 相结合,但如果我增加碰撞半径,我可以看到节点被推离框架,因此 Y 位置不会保留。

  var simulation = d3.forceSimulation(data.nodes)
    .force('links', d3.forceLink(data.links))
    .force('x', d3.forceX(width/2))      
    .force('collision', d3.forceCollide().radius(5))
    .force('y', d3.forceY( function(d) { 
      var date = moment(d.properties.date, "YYYY-MM-DD");
      var timepos = y_timescale(date)
      return timepos; }));

我的预感是我可以修改forceCollide()的来源并删除 y,但我只是将 D3 与 <script src="https://d3js.org/d3.v5.min.js"></script>一起使用,我不确定如何开始制作该部队的自定义版本。

编辑:我添加了更多上下文来响应以下答案:- 完整的代码示例在这里- 截图在这里

问题中的代码不足以保证这是您需要的,但要做出一些假设:

通常,当使用力布局时,您将允许力计算位置,然后在刻度时将节点重新定位到给定的 [x,y] 坐标,例如

function ticked() {
    nodeSelection.attr('cx', d => d.x).attr('cy', d => d.y);
}

由于您不希望力影响 y 坐标,只需将其从此处删除

即可
nodeSelection.attr('cx', d => d.x);

并设置 y 位置,比如说,输入:

nodeSelection = nodeSelection
    .enter()
    .append('circle')
    .attr('class', 'node')
    .attr('r', 2)
    .attr('cy', d => { 
      // Set y position based on scale here
    })
    .merge(nodeSelection);

最新更新