我想在 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);