D3.js的视觉Treelist

时间:2015-08-30 16:01:58

标签: javascript d3.js svg

我正在寻找一个解决方案,将一个D3.js层次结构树创建为一个树状列表,就像在MindNode 2中一样(参见:https://www.dropbox.com/s/6cjs1ma9n4yex3w/mindnode-treelist.png?dl=0)。

如您所见,有四种不同的路径:

  • 的一个重要起点
  • 一条线(用于不同的父路径)
  • 形曲线(父节点)
  • 节点“leafs”的形状的结尾
  • 形状的结尾,用于层次结构级别中的最后一个节点叶。

我发现这个例子似乎是一个良好的开端:http://bl.ocks.org/thehogfather/0e48ec486abbd5be17d7

我现在的问题是:我现在该怎么办?我想为每个节点附加一个svg容器,根据相关条件获取相关路径。另一个解决方案是一个巨大的svg及其所有路径 - 但这可能是错误的方式,因为 - 如图所示 - 一些节点有更多的文本必须包含在li - 元素内

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

1 个答案:

答案 0 :(得分:1)

在混淆了this awesome example of @mbostck的代码之后,我找到了一个解决方案并将我的代码从treelist布局重写为树形布局。但我将代码分为两部分:一部分是使用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列表。现在来看下一部分的魔力:你必须重新计算xy。我还使用了一个名为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

我将尝试通过更改插值类型,添加一些小的彩色节点圆等来优化它。

希望这会对某人有所帮助。

相关问题