Javascript D3.js可折叠力布局:未生成链接
我试图生成一个类似于此示例的可折叠力布局: 用于生成my force布局的数据是一个源于API的JSON对象。我能够成功地遍历数据结构,并生成附加到SVG的节点(根节点及其子节点) 但是,将父节点链接到其子节点时会出现问题没有生成链接,我的Links变量返回一个空数组。与示例相比,我非常确定这个问题与我的应用程序中的数据结构有关,因此我将发布我的JS代码和每个节点的数据结构 任何帮助都将不胜感激!提前谢谢Javascript D3.js可折叠力布局:未生成链接,javascript,api,svg,d3.js,force-layout,Javascript,Api,Svg,D3.js,Force Layout,我试图生成一个类似于此示例的可折叠力布局: 用于生成my force布局的数据是一个源于API的JSON对象。我能够成功地遍历数据结构,并生成附加到SVG的节点(根节点及其子节点) 但是,将父节点链接到其子节点时会出现问题没有生成链接,我的Links变量返回一个空数组。与示例相比,我非常确定这个问题与我的应用程序中的数据结构有关,因此我将发布我的JS代码和每个节点的数据结构 任何帮助都将不胜感激!提前谢谢 下面是我的代码: 以下是我的JS代码: //Force Layout Code var
下面是我的代码: 以下是我的JS代码:
//Force Layout Code
var w = 607,
h = 500,
node,
link,
root;
var force = d3.layout.force()
.on("tick", tick)
.size([w, h]);
var vis = d3.select("#chart").append("svg:svg")
.attr("width", w)
.attr("height", h);
function initiateForceJS(currentURL) {
//Generate the URL
forceURL = currentURL + ".json?jsonp=?";
$('#commentArea').show();
$.getJSON(forceURL,handleRequest2);
function handleRequest2(json) {
//Set the root as the first object returned
root = json[1]['data']['children'][0];
update();
}
}
function update() {
nodes = flatten(root),
links = d3.layout.tree()
.sort(null)
.children(function(d) {return (!d['replies']['data']['children']|| d['replies']['data']['children'].length === 0) ? null : d['replies']['data']['children'];})
.links(nodes);
// Restart the force layout.
force
.nodes(nodes)
.links(links)
.start();
// Update the links…
link = vis.selectAll("line.link")
.data(links, function(d) { return d.target.id; });
// Enter any new links.
link.enter().insert("svg:line", ".node")
.attr("class", "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; });
// Exit any old links.
link.exit().remove();
// Update the nodes…
node = vis.selectAll("circle.node")
.data(nodes, function(d) {return d.id; })
.style("fill", color);
// Enter any new nodes.
node.enter().append("svg:circle")
.attr("class", "node")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return Math.sqrt(d.ups) || 4.5; })
.style("fill", color)
//.on("click", click)
.call(force.drag);
// Exit any old nodes.
node.exit().remove();
//This will add the name of the character to the node
node.append("comment").text(function(d) { return d.body });
//This will put the comment in the Comment Area div
node.on("mouseover", function() {
var currentNode = d3.select(this);
var currentTitle = currentNode.select("comment").text();
$('#commentArea').html('<p>' + currentTitle + '</p>')
});
}
function tick() {
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; });
}
// Color leaf nodes orange, and packages white or blue.
function color(d) {
return d._children ? "#3182bd" : d.children ? "#c6dbef" : "#fd8d3c";
}
// Returns a list of all nodes under the root.
function flatten(root) {
var nodes = [], i = 0;
function recurse(node) {
if (node['data']['replies'] != "" && node['kind'] != "more") {
node['data']['replies']['data']['children'].forEach(recurse);
}
if (node['kind'] !="more") {
//Add an ID value to the node starting at 1
node.data.id = ++i;
var comment = node.data;
nodes.push(comment);
}
}
recurse(root);
return nodes;
}
//强制布局代码
var w=607,
h=500,
节点,
链接
根;
var-force=d3.layout.force()
.on(“滴答”,滴答)
.尺寸([w,h]);
var vis=d3.选择(“图表”).追加(“svg:svg”)
.attr(“宽度”,w)
.attr(“高度”,h);
函数initiateForceJS(当前URL){
//生成URL
forceURL=currentURL+“.json?jsonp=?”;
$('#commentArea').show();
$.getJSON(forceURL,handleRequest2);
函数handleRequest2(json){
//将根设置为返回的第一个对象
root=json[1]['data']['children'][0];
更新();
}
}
函数更新(){
节点=展平(根),
links=d3.layout.tree()
.sort(空)
.children(函数(d){return(!d['repries']['data']['children'].| d['repries']['data']['children'].['children'.]长度==0)?null:d['repries'.['data']['children'].})
.链接(节点);
//重新启动强制布局。
力
.节点(节点)
.链接(links)
.start();
//更新链接…
link=vis.selectAll(“line.link”)
.data(链接,函数(d){返回d.target.id;});
//输入任何新链接。
link.enter().insert(“svg:line”,“.node”)
.attr(“类”、“链接”)
.attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;});
//退出所有旧链接。
link.exit().remove();
//更新节点…
node=vis.selectAll(“circle.node”)
.data(节点,函数(d){return d.id;})
.样式(“填充”,颜色);
//输入任何新节点。
node.enter().append(“svg:circle”)
.attr(“类”、“节点”)
.attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;})
.attr(“r”,函数(d){return Math.sqrt(d.ups)| | 4.5;})
.样式(“填充”,颜色)
//.on(“单击”,单击)
.呼叫(强制拖动);
//退出所有旧节点。
node.exit().remove();
//这将向节点添加角色的名称
node.append(“comment”).text(函数(d){return d.body});
//这将把评论放在评论区div中
on(“mouseover”,function()){
var currentNode=d3.选择(此);
var currentTitle=currentNode.select(“comment”).text();
$('#commentArea').html(''+currentTitle+''))
});
}
函数tick(){
attr(“x1”,函数(d){返回d.source.x;})
.attr(“y1”,函数(d){返回d.source.y;})
.attr(“x2”,函数(d){返回d.target.x;})
.attr(“y2”,函数(d){返回d.target.y;});
attr(“cx”,函数(d){return d.x;})
.attr(“cy”,函数(d){返回d.y;});
}
//叶节点颜色为橙色,包装为白色或蓝色。
功能色(d){
返回d.#children?#3182bd:d.children?#c6dbef:#fd8d3c;
}
//返回根目录下所有节点的列表。
函数展平(根){
var节点=[],i=0;
函数递归(节点){
如果(节点['data']['replays']!=”&节点['kind']!=“more”){
节点['data']['replies']['data']['children'].forEach(递归);
}
如果(节点['kind']!=“more”){
//从1开始向节点添加ID值
node.data.id=++i;
var comment=node.data;
节点。推送(注释);
}
}
递归(根);
返回节点;
}
问题在于函数没有观察到您设置的子访问器;它仅依赖于节点的子节点
属性。这在原始示例中起作用,因为该示例使用标准的分层节点结构(每个节点上都有一个子节点
数组)。它在您的情况下不起作用,因为您使用的是非标准结构(由第三方API定义)
links方法不观察子访问器,因为当您对数据调用层次结构布局(如树布局)时,它会根据您定义的子访问器为您填充子访问器属性;它会自动将非标准输入数据映射到标准表单。但是,由于您没有在此处实际使用层次结构布局,因此没有机会将节点映射到标准格式,因此hierarchy.links不会返回任何结果。没有节点具有子节点
数组
这里的另一个问题是,您的根节点实际上没有任何回复,因此没有根节点的子节点。(有root.data.repress.data.children
,但没有定义root.repress.data.children
作为子访问器。)
我认为在这里最简单的做法是将数据映射到一个更简单的层次结构,其中子级定义为子级
数组。您可能可以使用层次结构布局来帮助实现这一点,但鉴于您已经编写了一个展平函数(或至少修改了一个),您已经完成了大部分工作。如果没有看到数据的完整结构,我认为不可能回答这个问题。例如,您的屏幕截图不会显示回复对象中的内容。你能