D3 新手,从我在互联网上发现的内容来看,很多问题/示例都相当过时,所以我很难找到解决方案。
最终我希望有一个由自动最佳间隔的节点和链接组成的网络图。有两个“起始”节点需要固定在中心。其余节点需要围绕这些节点间隔开。我不需要这个图表是可拖动的。
我的起点是这个力定向图。许多其他帖子提到固定节点的位置应该可行,其他节点自然会放置在该固定节点周围,但这不是我的经验。相反,虽然节点是固定的,但链接似乎被定位到空白空间(或节点本来所在的空间 - 参见下图)。
我正在像这样修复
ticked
函数中的节点:
function ticked() {
node
.attr('cx', (d) => {
if (d.id === 'NAME_ONE') {
return -50;
} else if (d.id === 'NAME_TWO') {
return 50;
} else {
return d.x;
}
})
.attr('cy', (d) => {
if (FIXED_NODES.includes(d.id)) {
return 0;
} else {
return d.y;
}
});
link
.attr('x1', (d) => d.source.x)
.attr('y1', (d) => d.source.y)
.attr('x2', (d) => d.target.x)
.attr('y2', (d) => d.target.y);
}
编辑: 我应该注意到,我已经尝试修复这两个节点之间的链接以及同一刻度函数内的链接,但这似乎也没有取得成果。当然有更简单的方法。
力模拟不跟踪 SVG 中的圆圈,它不知道它们。因此,改变圆的 cx/cy 对力模拟没有影响。
力模拟通过数据数组中节点的 d.x 和 d.y 属性跟踪节点(因此链接端点)。由于这些属性通常用于在 SVG 中放置圆和线,因此更改这些值将改变它们的位置。
D3 力模拟每次都会检查两个属性:d.fx 和 d.fy,如果设置了这些属性,则模拟将使用 d.fx 和 f.fy 属性在模拟中定位节点,而不是施加任何力(固定节点就位)。因此,在您的情况下,不要使用 cx 值修复 SVG 节点,而是使用 d.fx 修复数据项:
if (d.id === 'NAME_ONE') {
d.fx = -50;
}
现在您可以将带有 d.x 的所有节点放置在 tick 函数中。
当然,您不需要每次都设置 d.fx(除非您在模拟过程中更改节点的名称),您可以在开始时运行一次节点,并在适当的情况下设置一次 fx/fy 属性。