block by mhkeller caef4ae1d93976c2c6ea1a9c28c8991a

d3-hierarchy tree

Full Screen

A visualization of files in d3-hierarchy, based on Radial Tidy Tree.

Data Collection

Use git to clone a repository, then du to create a tsv with the directory contents.

git clone https://github.com/d3/d3-hierarchy.git
(echo -n 'size\tfile\n'; du -a d3-hierarchy/*) > d3-hierarchy.tsv

Burrow - recursive nesting

An updated version of the burrow function from d3 src tree in plain JavaScript. This function takes an array of keys to generate a hierarchy.

Compared to d3.nest: burrow allows for branches of arbitrary depth.

Compared to d3.stratify: parent nodes do not need to be specified as separate rows in the tabular data. Parents are created automatically as they are encountered.

index.html

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.node circle {
  fill: #999;
}

.node text {
  font: 10px sans-serif;
}

.node--internal circle {
  fill: #555;
}

.node--internal text {
  text-shadow: 0 1px 0 #fff, 0 -1px 0 #fff, 1px 0 0 #fff, -1px 0 0 #fff;
}

.link {
  fill: none;
  stroke: #555;
  stroke-opacity: 0.4;
  stroke-width: 1.5px;
}

</style>
<body>
<script src="//d3js.org/d3.v4.0.0-alpha.29.js"></script>
<script>

var width = 960,
    height = 500,
    radius = 250;

var burrow = function(table) {
  // create nested object
  var obj = {};
  table.forEach(function(row) {
    // start at root
    var layer = obj;

    // create children as nested objects
    row.taxonomy.forEach(function(key) {
      layer[key] = key in layer ? layer[key] : {};
      layer = layer[key];
    });
  });

  // recursively create children array
  var descend = function(obj, depth) {
    var arr = [];
    var depth = depth || 0;
    for (var k in obj) {
      var child = {
        name: k,
        depth: depth,
        children: descend(obj[k], depth+1)
      };
      arr.push(child);
    }
    return arr;
  };

  // use descend to create nested children arrys
  return {
    name: "root",
    children: descend(obj, 1),
    depth: 0
  }
};
    
var tree = d3.tree()
    .size([360, radius - 90])
    .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2) / a.depth; });

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + (width / 2) + "," + (height / 2) + ")");

d3.tsv("d3-hierarchy.tsv", function(error, data) {
  if (error) throw error;

  // splitting keys into an array is required before passing data into burrow
  data.forEach(function(row) {
    row.taxonomy = row.file.split("/");
  });

  var root = d3.hierarchy(burrow(data));

  tree(root);

  var link = svg.selectAll(".link")
      .data(root.descendants().slice(1))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", function(d) {
        return "M" + project(d.x, d.y)
            + "C" + project(d.x, (d.y + d.parent.y) / 2)
            + " " + project(d.parent.x, (d.y + d.parent.y) / 2)
            + " " + project(d.parent.x, d.parent.y);
      });

  var node = svg.selectAll(".node")
      .data(root.descendants())
    .enter().append("g")
      .attr("class", function(d) { return "node" + (d.children ? " node--internal" : " node--leaf"); })
      .attr("transform", function(d) { return "translate(" + project(d.x, d.y) + ")"; });

  node.append("circle")
      .attr("r", 2.5);

  node.append("text")
      .attr("dy", ".31em")
      .attr("x", function(d) { return d.x < 180 === !d.children ? 6 : -6; })
      .style("text-anchor", function(d) { return d.x < 180 === !d.children ? "start" : "end"; })
      .attr("transform", function(d) { return "rotate(" + (d.x < 180 ? d.x - 90 : d.x + 90) + ")"; })
      .text(function(d) { return d.data.name; });
});

function project(x, y) {
  var angle = (x - 90) / 180 * Math.PI, radius = y;
  return [radius * Math.cos(angle), radius * Math.sin(angle)];
}

</script>

d3-hierarchy.tsv

size	file
8	LICENSE
72	README.md
8	d3-hierarchy.sublime-project
88	img/cluster.png
200	img/pack.png
56	img/partition.png
72	img/stratify.png
72	img/tree.png
144	img/treemap.png
632	img
8	index.js
8	package.json
8	src/accessors.js
8	src/cluster.js
8	src/constant.js
8	src/hierarchy/ancestors.js
8	src/hierarchy/descendants.js
8	src/hierarchy/each.js
8	src/hierarchy/eachAfter.js
8	src/hierarchy/eachBefore.js
8	src/hierarchy/index.js
8	src/hierarchy/leaves.js
8	src/hierarchy/path.js
8	src/hierarchy/sort.js
8	src/hierarchy/sum.js
80	src/hierarchy
8	src/pack/enclose.js
8	src/pack/index.js
8	src/pack/shuffle.js
8	src/pack/siblings.js
32	src/pack
8	src/partition.js
8	src/stratify.js
16	src/tree.js
8	src/treemap/binary.js
8	src/treemap/dice.js
8	src/treemap/index.js
8	src/treemap/round.js
8	src/treemap/slice.js
8	src/treemap/sliceDice.js
8	src/treemap/squarify.js
56	src/treemap
224	src
136	test/data/flare-one.json
136	test/data/flare-phi.json
16	test/data/flare.csv
24	test/data/flare.json
8	test/data/simple.json
8	test/data/simple2.json
8	test/data/simple3.json
336	test/data
24	test/stratify-test.js
8	test/treemap/binary-test.js
8	test/treemap/dice-test.js
8	test/treemap/flare-test.js
16	test/treemap/index-test.js
8	test/treemap/round.js
8	test/treemap/slice-test.js
8	test/treemap/sliceDice-test.js
8	test/treemap/squarify-test.js
72	test/treemap
432	test