Javascript 在d3力定向网络中设置初始位置后的NaN节点位置
我正在D3中创建一个强制定向网络,其中每个节点代表集合中的一个网页,它们之间的定向链接代表从一个网页到另一个网页的超链接。当用户在网页之间移动时,链接会添加到网络中。集合中的节点数/网页数不变 每当添加新链接时,我都会重新加载网络,读取包含新旧链接和所有节点的JSON代码。目前,我正试图“平静”这个网络的初始负载,这样节点就不会在随机的地方创建,可能会创建一个节点与以前的位置相去甚远的网络。为此,我想将每个节点的初始位置设置为前一个网络中的位置 我通过设置节点的x和y属性完成了此操作,如以下代码段所示:Javascript 在d3力定向网络中设置初始位置后的NaN节点位置,javascript,d3.js,force-layout,Javascript,D3.js,Force Layout,我正在D3中创建一个强制定向网络,其中每个节点代表集合中的一个网页,它们之间的定向链接代表从一个网页到另一个网页的超链接。当用户在网页之间移动时,链接会添加到网络中。集合中的节点数/网页数不变 每当添加新链接时,我都会重新加载网络,读取包含新旧链接和所有节点的JSON代码。目前,我正试图“平静”这个网络的初始负载,这样节点就不会在随机的地方创建,可能会创建一个节点与以前的位置相去甚远的网络。为此,我想将每个节点的初始位置设置为前一个网络中的位置 我通过设置节点的x和y属性完成了此操作,如以下代码
var links = data.links;
var nodes = data.nodes;
var nodeDictionary = new Object();
if (node != 0) {
force.stop();
node.each(function(d) {
var pos = [];
var thisNode = d3.select(this);
pos[0] = thisNode.attr("x");
pos[1] = thisNode.attr("y");
var page = thisNode.attr("page");
nodeDictionary[page] = pos;
});
nodes.forEach(function(node) {
var x = nodeDictionary[node.id][0];
var y = nodeDictionary[node.id][1];
//node.px = undefined;
//node.py = undefined;
node.x = x;
node.y = y;
});
}
这似乎在某些时间或对某些节点有效,但大多数情况下,这会导致节点具有NaN位置。具体来说,这些位置在网络的tick()方法中为NaN,如下所示:
// Animates the force-directed network
function tick() {
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
link.attr("d", drawCurve);
}
function drawCurve(d) {
var testing = "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y;
return testing
}
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
在其他示例中,我看到在力定向网络中设置初始节点位置时,tick()方法看起来更像这样:
// Animates the force-directed network
function tick() {
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
link.attr("d", drawCurve);
}
function drawCurve(d) {
var testing = "M" + d.source.x + "," + d.source.y + "L" + d.target.x + "," + d.target.y;
return testing
}
force.on("tick", function() {
link.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
我还需要做些什么来使用translate函数使代码正常工作?在创建一个新的网络之前,我也尝试过停止tick方法,正如本文所建议的那样,但是没有帮助。在生成新网络之前,是否需要清除某些变量或元素?我还尝试过设置px和py属性以及px、py、x和y属性的各种值组合,但没有成功
我创建了一个JSFIDLE,其中的基本代码显示了我在这里遇到的问题:
双击任一节点将生成一个新网络。一些节点已正确设置为其以前的位置,但具有NaN位置的节点将移动到左上角。关键在于更改此业务:
node.each(function(d) {
var pos = [];
var thisNode = d3.select(this);
pos[0] = thisNode.attr("x");
pos[1] = thisNode.attr("y");
var page = thisNode.attr("page");
nodeDictionary[page] = pos;
});
为此:
node.each(function(d) {
pos = [];
pos[0] = d.x;
pos[1] = d.y;
var page = d.id;
nodeDictionary[page] = pos;
});
由于我使用了.attr(“x”)和.attr(“y”),所以发生了奇怪的事情。还有,诅咒我对D3的不熟悉 该代码片段严重混乱,但我猜数据集中的
id
属性并不总是等于从
元素中提取的“page”属性。对于奇怪的代码,我深表歉意。页面属性应该与id匹配。进行快速测试时,看起来每个节点都按预期分配了一个x和一个y。使用page属性存储在nodeDictionary中的位置与分配给具有匹配id的节点的位置相匹配。嗯,我必须出于不同的原因获取我的NaN
。请注意,前三行可以写成pos=[d.x,d.y]
。