2015-08-30 92 views
1

我正在寻找一种解决方案,将D3.js层次树制作为树形结构树,如MindNode 2(请参阅:https://www.dropbox.com/s/6cjs1ma9n4yex3w/mindnode-treelist.png?dl=0)。D3.js的视觉化列表

正如你看到有四种不同的路径:

  • 一大出发点根
  • 线(对于不同的父路径)
  • 一个形曲线(用于父节点)
  • 节点的形端“叶子”
  • 用于在层级中的最后节点的叶形端。

我发现这个例子似乎想成为一个好的开始工作:http://bl.ocks.org/thehogfather/0e48ec486abbd5be17d7

我的问题是,现在我应该怎么现在继续?我想为每个根据相关条件获取相关路径的节点添加一个svg容器。另一种解决方案将是一个巨大的svg及其所有路径 - 但这可能是错误的方式,因为 - 正如您在图像中看到的 - 一些节点有更多的文本必须包装在li元素中。

任何解决方案?打开问题?例子 :-) ?

+0

这就是现在的样子:https://www.dropbox.com/s/2dia1jicjzpv0wt/treelist-vis.png?dl=0 –

回答

1

在混淆了this awesome example of @mbostck的代码后,我找到了一个解决方案,并将我的代码从树列布局重新编排到树布局。但是我将代码分为两部分:一部分是用ulli HTML元素构建列表。另一部分是用一个大的svg画出路径。

所以第一部分的代码为以下几点:

// This is my HTML container element 
    var $treelistContainer = d3.select('#treelist'); 

    var tree = d3.layout.tree(); 

    var indent = 15, 
     nodeTree = 0; 
    var ul = $treelistContainer.append("ul").classed("treelist",true); 

    var nodes = tree.nodes(data); 

    var nodeEls = ul.selectAll("li.item").data(nodes); 
    //list nodes 
    var listEnter = nodeEls 
    .enter() 
     .append("li") 
     .attr("class", function(d) { 
      // set class to node and to leaf (for endpoints) or to root (for stem) 
      var output = 'item'+(d.parent ? d.children ? '' : ' leaf' : ' root'); 

      // set class to even or to odd, based on its level; 
      output += ((d.depth % 2) === 0 ? ' even' : ' odd'); 

      return output; 
     }) 
     .attr("id", function(d,i){return "id"+i}) 
     .style("opacity", 1) 
     .style("background-color", function(d) { 
      return colorgrey(d.depth); 
     }) 
     .append("span").attr("class", "value") 
      .style("padding-left", function (d) { 
      return 20 + d.depth * indent + "px"; 
      }) 
      .html(function (d) { return d.name; }); 

即建立了项目的整个HTML列表。现在来看下一部分的魔力:你必须重新计算x,y。我还使用了一个名为nodeTree的值来为每个层次结构分配一个自己的ID以为其选择不同的颜色。因此,这里的代码:

var nodeTree = 0; 
var rootTop = d3.selectAll('li.item') 
    .filter(function(d,i) { 
     return i == 0; 
    }) 
    .node() 
     .getBoundingClientRect() 
     .top; 
nodes.forEach(function(n, i) { 
    // Get position of li element 
    var top = d3.selectAll('li.item') 
    .filter(function(d2,i2) { 
     return i2 == i; 
    }) 
    .node() 
     .getBoundingClientRect() 
     .top; 
    n.x = top - rootTop;//i * 38; 
    n.y = n.depth * indent; 
    if (n.depth == 1) nodeTree++; 
    n.value = nodeTree; 
}); 

下面我简单宣读了X,Y和值来计算它的对角线位置。之前,我必须建立容器和计算一些其他的东西

var width = $treelistContainer.node().getBoundingClientRect().width, 
     height = $treelistContainer.node().getBoundingClientRect().height, 
     i = 0, 
     id = 0, 
     margin = {top: 20, right: 10, bottom: 10, left: 15}; 

    var diagonal = d3.svg.diagonal() 
    .projection(function(d) { return [d.y, d.x]; }); 

    var svg = $treelistContainer 
    .append("svg") 
     .attr("width", width - margin.left - margin.right+"px") 
     .attr("height", height+"px") 
     .append("g") 
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

    var link = svg.selectAll("path.link") 
    .data(tree.links(nodes)) 
     .enter() 
     .insert("path", "g") 
     .attr("class", "link") 
     .attr("stroke", function(d) { 

      // Setting the color based on the hierarchy 
      console.log(d.target.value); 
      return color(d.target.value); 
     }) 
     .attr("d", function(d,i) { 
      var source = {x: d.source.x, y: d.source.y}; 
      var target = {x: d.target.x, y: d.target.y}; 
      return diagonal({source: source, target: target}); 
     }); 

这里是它的样子:https://www.dropbox.com/s/ysbszycoiost72t/result.png?dl=0

我会尝试通过改变插值类型,增加了一些小丰富多彩的节点圆圈进行优化和等等。

希望这会帮助别人。