D3 - 定位边缘抛出 NaN 错误
D3 - positioning edges is throwing NaN errors
根据 Stephen Thomas https://github.com/sathomas/jsDataV.is-source/tree/master/ch7/force 的指导,我尝试制作了一个 d3 力布局图。
然而,我被困在一个错误中,我不知道错误的来源以及如何解决它。
鉴于以下 plunker http://plnkr.co/edit/Bx0qe8DNEsnFgLhkxbfS?p=preview 此代码段导致
var positionEdge = function(edge, nodes) {
edge.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; });
};
许多错误,例如错误:属性 y2="NaN"
的值无效
我按如下方式构建边缘数组,但要完全重现问题,请使用 plunker link:
var edges = [];
links.forEach(function(srcLink){
var targetNodeId;
var targetNodeName;
var sourceNodeId;
var sourceNodeName;
nodes.forEach(function(srcNode){
if(srcNode.label === srcLink.source){
sourceNodeId = srcNode.id;
sourceNodeName = srcNode.label;
} else if(srcNode.label === srcLink.target){
targetNodeId = srcNode.id;
targetNodeName = srcNode.label;
}
})
edges.push({
"id": "From_" + sourceNodeName + "_To_" + targetNodeName,
"target": targetNodeId,
"source": sourceNodeId
});
})
// remove duplicate edges
var arr = {};
for ( var i=0, len=edges.length; i < len; i++ )
arr[edges[i]['id']] = edges[i];
edges = new Array();
for ( var key in arr )
edges.push(arr[key]);
调用 positionEdge 函数时引发所有 NaN 错误的原因是什么?
你边上的 source
和 target
字段似乎是节点 ID,而不是对象。您有两个解决方案:
使用对象:
edges.push({
"id": "From_" + sourceNodeName + "_To_" + targetNodeName,
"target": nodes[targetNodeId],
"source": nodes[sourceNodeId]
});
或
使用索引(坏主意,请参阅下面的编辑说明)
var positionEdge = function(edge, nodes) {
edge.attr("x1", function(d) { return nodes[d.source].x; })
.attr("y1", function(d) { return nodes[d.source].y; })
.attr("x2", function(d) { return nodes[d.target].x; })
.attr("y2", function(d) { return nodes[d.target].y; });
};
d3
中的标准是使用第一个选项,但如果您愿意,可能会对您的代码进行其他编辑。使用第二个选项,每次需要边缘端点时,您将不得不使用节点 [d.source] 和节点 [d.target]。
编辑:实际上,force
布局会自动将基于索引的边转换为基于对象的边。因此,除非您为边缘使用两个不同的数组,否则您需要选择第一个选项。
根据 Stephen Thomas https://github.com/sathomas/jsDataV.is-source/tree/master/ch7/force 的指导,我尝试制作了一个 d3 力布局图。
然而,我被困在一个错误中,我不知道错误的来源以及如何解决它。
鉴于以下 plunker http://plnkr.co/edit/Bx0qe8DNEsnFgLhkxbfS?p=preview 此代码段导致
var positionEdge = function(edge, nodes) {
edge.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; });
};
许多错误,例如错误:属性 y2="NaN"
的值无效我按如下方式构建边缘数组,但要完全重现问题,请使用 plunker link:
var edges = [];
links.forEach(function(srcLink){
var targetNodeId;
var targetNodeName;
var sourceNodeId;
var sourceNodeName;
nodes.forEach(function(srcNode){
if(srcNode.label === srcLink.source){
sourceNodeId = srcNode.id;
sourceNodeName = srcNode.label;
} else if(srcNode.label === srcLink.target){
targetNodeId = srcNode.id;
targetNodeName = srcNode.label;
}
})
edges.push({
"id": "From_" + sourceNodeName + "_To_" + targetNodeName,
"target": targetNodeId,
"source": sourceNodeId
});
})
// remove duplicate edges
var arr = {};
for ( var i=0, len=edges.length; i < len; i++ )
arr[edges[i]['id']] = edges[i];
edges = new Array();
for ( var key in arr )
edges.push(arr[key]);
调用 positionEdge 函数时引发所有 NaN 错误的原因是什么?
你边上的 source
和 target
字段似乎是节点 ID,而不是对象。您有两个解决方案:
使用对象:
edges.push({ "id": "From_" + sourceNodeName + "_To_" + targetNodeName, "target": nodes[targetNodeId], "source": nodes[sourceNodeId] });
或
使用索引(坏主意,请参阅下面的编辑说明)
var positionEdge = function(edge, nodes) { edge.attr("x1", function(d) { return nodes[d.source].x; }) .attr("y1", function(d) { return nodes[d.source].y; }) .attr("x2", function(d) { return nodes[d.target].x; }) .attr("y2", function(d) { return nodes[d.target].y; }); };
d3
中的标准是使用第一个选项,但如果您愿意,可能会对您的代码进行其他编辑。使用第二个选项,每次需要边缘端点时,您将不得不使用节点 [d.source] 和节点 [d.target]。
编辑:实际上,force
布局会自动将基于索引的边转换为基于对象的边。因此,除非您为边缘使用两个不同的数组,否则您需要选择第一个选项。