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

时间:2019-05-29 15:57:05

标签: javascript d3.js

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

我尝试将碰撞力与forceY组合在一起,但是如果增加碰撞半径,我会看到节点被推离框架,因此不会保留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()修改source并删除y,但是我只是将D3与<script src="https://d3js.org/d3.v5.min.js"></script>一起使用,我不确定如何开始制作自定义版本的力量。

编辑:完整代码示例here

1 个答案:

答案 0 :(得分:0)

问题中没有足够的代码来保证这是您所需要的,但是要作一些假设:

通常,当使用力布局时,您将允许力计算位置,然后将节点重新定位到刻度上的给定[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);