D3.js可折叠力布局:不被生成的链接 [英] D3.js Collapsible Force Layout: Links are not being generated

查看:568
本文介绍了D3.js可折叠力布局:不被生成的链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想生成类似于此示例可折叠力布局: HTTP://bl.ocks .ORG / mbostock / 1062288

中的数据被用来生成我力量的布局是从API被采购的JSON对象。我成功能够遍历该数据结构中,并生成附加到SVG(包括根节点和他们的孩子)。

的节点

然而,问题自带的父节点链接到自己的孩子节点。不被生成的链接,我的链接变量返回一个空数组。我是pretty确保该问题已是与数据是如何在我的应用程序的结构相比,例如,所以我会后我的JS code和各节点的数据结构两者。

任何帮助将是非常美联社preciated!在此先感谢!

下面是一个JS拨弄我的code: http://jsfiddle.net/tmzjW/

下面是我的JS code:

  //强制布局code
变种W = 607,
    H = 500,
    节点,
    链接,
    根;VAR力= d3.layout.force()
    。对(滴答,打勾)
    .size([W,H]);。VAR可见= d3.select(#表)追加(SVG:SVG)
    .attr(宽度,W)
    .attr(高度,H);功能initiateForceJS(CURRENTURL){
    //生成URL
    forceURL = CURRENTURL +?以.json JSONP =?;
    $('#commentArea)显示()。
    $ .getJSON(forceURL,handleRequest2);
    功能handleRequest2(JSON){
        //设置ro​​ot作为第一个对象返回
        根= json的[1] ['数据'] ['孩子'] [0];
        更新();
    }
}功能更新(){
  节点=扁平化(根),
  链接= d3.layout.tree()
            的.sort(空)
            。儿童(函数(D){返回(!D ['回复'] ['数据'] ['孩子'] || D ['回复'] ['数据'] ['孩子'。长度=== 0)空:D ['回复'] ['数据'] ['孩子'];})
            .links(节点);  //重新启动力布局。
  力
      .nodes(节点)
      .links(链接)
      。开始();  //更新链接...
  链接= vis.selectAll(line.link)
      。数据(链接功能(D){返回d.target.id;});  //输入任何新的链接。
  。link.enter()插入(SVG:线,.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()删除();  //更新节点...
  节点= vis.selectAll(circle.node)
      。数据(节点,功能(D){返回d.id;})
      .style(补,颜色);  //进入任何新的节点。
  。node.enter()追加(SVG:圈)
      .attr(类,节点)
      .attr(CX功能(D){返回d.x;})
      .attr(CY功能(D){返回d.y;})
      .attr(R功能(D){返回的Math.sqrt(d.ups)|| 4.5;})
      .style(补,颜色)
      //.on(\"click,点击)
      .CALL(force.drag);  //退出所有旧节点。
  。node.exit()删除();
  //这将添加的字符的名称的节点  node.append(意见),文本(功能(D){返回d.body})。
  //这将使在注释区域DIV评论
  node.on(鼠标悬停功能(){
    VAR currentNode = d3.select(本);
    。VAR currentTitle = currentNode.select(意见),文本();
    $('#commentArea)HTML。('< P>'+ currentTitle +'< / P>')
  });
}
功能打勾(){
  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;});  node.attr(CX功能(D){返回d.x;})
      .attr(CY功能(D){返回d.y;});
}//颜色叶子节点橙色,包白色或蓝色。
功能颜色(D){
  返回d._children? #3182bd:d.children? #c6dbef:#fd8d3c;
}
//返回根下的所有节点的列表。
扁平化的功能(根){
  VAR节点= [],I = 0;
  函数递归(节点){    如果(节点['数据'] ['回复'] =!&放大器;&安培;节点['种'] =!更多){
        。节点['数据'] ['回复'] ['数据'] ['孩子们']的forEach(递归);
    }
    如果(节点['种']!=更多){
        //一个ID值添加到节点开始于1
        node.data.id = ++我;
        VAR评论= node.data;
        nodes.push(注解);
    }
  }
  递归(根);
  返回节点;
}


解决方案

的问题是,的 hierarchy.links 功能无法观察患儿存取器设置;完全依靠的孩子节点的属性。这部作品在原来的例子,因为该示例使用标准的层次节点结构(每个节点上一个孩子数组)。因为您使用的是非标准的结构(由第三方API定义)它不会工作你的情况。

的联系方法,因为当你调用一个层次布局(如树布局)上的数据不遵守儿童访问,它将填充孩子属性您根据孩子们访问器定义;它的非标准输入数据自动映射到标准形式。但是,因为你没有实际使用层次布局在这里,它有没有机会节点映射到标准格式,从而hierarchy.links回报没有结果,没有节点有一个孩子阵列。

这里的另一个问题是,你的节点实际上没有任何答复,所以有没有孩子的根节点。 (有 root.data.replies.data.children ,而不是 root.replies.data.children 为您的孩子访问定义。)

我想在这里做最简单的事情是将您的数据映射到一个简单的分层结构,在那里孩子们定义为孩子阵列。你也许能够使用的层次结构布局,以帮助这一说法,但考虑到你已经写了一个扁平化的功能(或者至少是经过修改的),你最的方式反正有。

I'm trying to generate a collapsible force layout similar to this example: http://bl.ocks.org/mbostock/1062288:

The data being used to generate my force layout is a JSON object being sourced from an API. I am successfully able to traverse the data structure, and generate nodes that are appended to the SVG (both root nodes and their children).

However, the issue comes with linking the parent nodes to their children nodes. Links are not being generated, and my links variable is returning an empty array. I'm pretty sure that the issue has something to do with how the data is structured in my app compared to the example, so I'll post both my JS code and the data structure of each node.

Any help would be much appreciated! Thanks in advance!!

Here's a JS Fiddle with my code: http://jsfiddle.net/tmzjW/

Here is my JS code:

//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;
}

解决方案

The problem is that hierarchy.links function does not observe the children accessor you set; it relies solely on the children property of nodes. This works in the original example because that example uses the standard hierarchical node structure (which a children array on each node). It doesn’t work in your case because you’re using a nonstandard structure (defined by a third-party API).

The links method doesn't observe the children accessor because when you invoke a hierarchy layout (such as the tree layout) on data, it populates the children property for you based on the children accessor you define; it maps your nonstandard input data to the standard form automatically. However, since you’re not actually using the hierarchy layout here, it has no opportunity to map the nodes to the standard format, and thus hierarchy.links returns no results—no nodes have a children array.

The other problem here is that your root node doesn't actually have any replies, so there are no children of the root node. (There’s root.data.replies.data.children, but not root.replies.data.children as your children accessor is defined.)

I think the simplest thing to do here would be to map your data to a simpler hierarchical structure, where the children are defined as a children array. You might be able to use the hierarchy layout to help with that, but given that you've already written a flatten function (or at least modified one), you're most of the way there anyway.

这篇关于D3.js可折叠力布局:不被生成的链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆