2015-08-30 93 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

我會嘗試通過改變插值類型,增加了一些小豐富多彩的節點圓圈進行優化和等等。

希望這會幫助別人。