我已经根据这个力导向图示例用 D3.js 构建了一个图,但我不是在节点之间使用直线,而是使用SVG 路径元素创建曲线。单个链接的数据结构包括源和目标,它们表示链接所连接的节点。此外,链接数据结构还包含一个线元素,其中包含定义路径的点数组。链接的数据结构如下所示:
{
id:4,
type:"link",
fixed:true,
source: {
id:1,
name: "A",
type:"node",
x:226,
y:190,
fixed:1,
index:0,
weight:1,
},
target: {
id:2,
name: "B",
type:"node",
x:910,
y:85,
fixed:1,
index:1,
weight:1,
},
line:[{x:387, y:69}, {x:541.5, y:179}, {x:696, y:179}]
}
现在,在我的 on tick事件处理程序中,我通过引用d.source.x、d.source.y和d.target.x、 d.target 获得了节点A和B的当前x和y坐标。是的。我还有节点 A(d.line的第一个元素)和节点 B(d.line的最后一个元素)的初始位置。我要做的是根据对节点A和B的位置所做的更改重新计算第一个点和最后一个点之间的点。
这是我的 on tick事件处理程序:
force.on("tick", function() {
svg.selectAll("g.node").attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
svg.selectAll("g.link .line").attr("d", function(d) {
var xOffset = 0, // Want to calculate this
yOffset = 0; // Want to calculate this
var line = [ ];
for (var i=0; i<d.line.length; i++) {
if (i==0) {
line[line.length] = { x : d.source.x, y: d.source.y }
}
else if (i==d.line.length-1) {
line[line.length] = { x : d.target.x, y: d.target.y }
}
else {
line[line.length] = { x: d.line[i].x + xOffset, y: d.line[i].y + yOffset }
}
}
return self.lineGenerator(line);
})
});
不偏移路径中间点的x和y坐标会导致这些点在拖动节点 A 或 B 时保持静止。谁能解释如何计算xOffset和yOffset以便在拖动节点时路径将正确移动/旋转?或者,如果有人知道使用 D3.js 完成此任务的更好(阅读“更简单”!)方法,请告诉我。
更新:
这是图表构造函数中的线生成器代码:
this.lineGenerator = d3.svg.line() .x(function(d) { return dx; }) .y(function(d) { return dy; }) .interpolate("cardinal");
让我用一些图像来解释问题,希望它们能让我遇到的问题更清楚。线不是线性的问题,我的线是由线生成器弯曲的,但是当我拖动节点时,我希望曲线也拖动。因此,线上的所有点都必须更新以反映对节点位置所做的更改。换句话说,路径不能被正在移动的节点扭曲。
所以,在图片中;鉴于这种情况:
如果我将节点 B 向下和向左拖动,我希望看到如下内容:
(注意这是用图像编辑软件旋转的,因此背景也旋转了)
相反,我得到的是这样的:
请注意,当节点 B 移动时,线中的一个中间点如何保持静止,从而导致曲线扭曲。这是我试图避免发生的事情。
希望这可以使问题更清楚。