block by gka 5145845

d3 inter-dependency graph

Full Screen

An implementation of Danny Holten‘s hierarchical edge bundling algorithm in D3, showing dependencies between classes in d3 functions hierarchy. Dependencies are bundled according to the parent packages. This example uses two layouts: a radial d3.layout.cluster to position the tree nodes, and d3.layout.bundle to group the dependencies into spline bundles. Thanks to Jason Davies for contributing the layout implementation!

index.html

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

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

.link {
  stroke: steelblue;
  stroke-opacity: 0.6;
  fill: none;
}

</style>
<body>
<script src="//d3js.org/d3.v3.min.js"></script>
<script>

var diameter = 960,
    radius = diameter / 2,
    innerRadius = radius - 120;

var cluster = d3.layout.cluster()
    .size([360, innerRadius])
    .sort(null)
    .value(function(d) { return d.size; });

var bundle = d3.layout.bundle();

var line = d3.svg.line.radial()
    .interpolate("bundle")
    .tension(0.55)
    .radius(function(d) { return d.y; })
    .angle(function(d) { return d.x / 180 * Math.PI; });

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

d3.json("readme-d3-imports.json", function(error, classes) {

  var nodes = cluster.nodes(packages.root(classes)),
      links = packages.imports(nodes);

  svg.selectAll(".link")
      .data(bundle(links))
    .enter().append("path")
      .attr("class", "link")
      .attr("d", line);

  svg.selectAll(".node")
      .data(nodes.filter(function(n) { return !n.children; }))
    .enter().append("g")
      .attr("class", "node")
      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
    .append("text")
      .attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
      .attr("dy", ".31em")
      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
      .text(function(d) { return d.key; });
});

d3.select(self.frameElement).style("height", diameter + "px");

var packages = {

  // Lazily construct the package hierarchy from class names.
  root: function(classes) {
    var map = {};

    function find(name, data) {
      var node = map[name], i;
      if (!node) {
        node = map[name] = data || {name: name, children: []};
        if (name.length) {
          node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
          if (!node.parent.children) {
            node.parent.children = [];
          }
          node.parent.children.push(node);
          node.key = name.substr(3);//name.substring(i + 1);
        }
      }
      return node;
    }

    classes.forEach(function(d) {
      find(d.name, d);
    });

    return map[""];
  },

  // Return a list of imports for the given array of nodes.
  imports: function(nodes) {
    var map = {},
        imports = [];

    // Compute a map from name to node.
    nodes.forEach(function(d) {
      map[d.name] = d;
    });

    // For each import, construct a link from the source to target node.
    nodes.forEach(function(d) {
      if (d.imports) d.imports.forEach(function(i) {
        imports.push({source: map[d.name], target: map[i]});
      });
    });

    return imports;
  }
};

</script>

bundle.html


<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
    <link type="text/css" rel="stylesheet" href="style.css"/>
    <style type="text/css">

path.arc {
  cursor: move;
  fill: #fff;
}

.node {
  font-size: 10px;
}

.node:hover {
  fill: #1f77b4;
}

.link {
  fill: none;
  stroke: #1f77b4;
  stroke-opacity: .4;
  pointer-events: none;
}

.link.source, .link.target {
  stroke-opacity: 1;
  stroke-width: 2px;
}

.node.target {
  fill: #d62728 !important;
}

.link.source {
  stroke: #d62728;
}

.node.source {
  fill: #2ca02c;
}

.link.target {
  stroke: #2ca02c;
}

    </style>
  </head>
  <body>
    <h2>
      D3 imports<br>
      hierarchical edge bundling
    </h2>
    <div style="position:absolute;bottom:0;font-size:18px;">tension: <input style="position:relative;top:3px;" type="range" min="0" max="100" value="85"></div>
    <script src="//d3js.org/d3.v3.min.js"></script>

    <script type="text/javascript" src="packages.js"></script>
    <script type="text/javascript">

var w = 1280,
    h = 800,
    rx = w / 2,
    ry = h / 2,
    m0,
    rotate = 0;

var splines = [];

var cluster = d3.layout.cluster()
    .size([360, ry - 120])
    .sort(function(a, b) { return d3.ascending(a.key, b.key); });

var bundle = d3.layout.bundle();

var line = d3.svg.line.radial()
    .interpolate("bundle")
    .tension(.85)
    .radius(function(d) { return d.y; })
    .angle(function(d) { return d.x / 180 * Math.PI; });

// Chrome 15 bug: <//code.google.com/p/chromium/issues/detail?id=98951>
var div = d3.select("body").insert("div", "h2")
    .style("top", "-80px")
    .style("left", "-160px")
    .style("width", w + "px")
    .style("height", w + "px")
    .style("position", "absolute");

var svg = div.append("svg:svg")
    .attr("width", w)
    .attr("height", w)
  .append("svg:g")
    .attr("transform", "translate(" + rx + "," + ry + ")");

svg.append("svg:path")
    .attr("class", "arc")
    .attr("d", d3.svg.arc().outerRadius(ry - 120).innerRadius(0).startAngle(0).endAngle(2 * Math.PI))
    .on("mousedown", mousedown);

d3.json("readme-d3-imports.json", function(classes) {
  var nodes = cluster.nodes(packages.root(classes)),
      links = packages.imports(nodes),
      splines = bundle(links);

  var path = svg.selectAll("path.link")
      .data(links)
    .enter().append("svg:path")
      .attr("class", function(d) { return "link source-" + d.source.key + " target-" + d.target.key; })
      .attr("d", function(d, i) { return line(splines[i]); });

  svg.selectAll("g.node")
      .data(nodes.filter(function(n) { return !n.children; }))
    .enter().append("svg:g")
      .attr("class", "node")
      .attr("id", function(d) { return "node-" + d.key; })
      .attr("transform", function(d) { return "rotate(" + (d.x - 90) + ")translate(" + d.y + ")"; })
    .append("svg:text")
      .attr("dx", function(d) { return d.x < 180 ? 8 : -8; })
      .attr("dy", ".31em")
      .attr("text-anchor", function(d) { return d.x < 180 ? "start" : "end"; })
      .attr("transform", function(d) { return d.x < 180 ? null : "rotate(180)"; })
      .text(function(d) { return d.key; })
      .on("mouseover", mouseover)
      .on("mouseout", mouseout);

  d3.select("input[type=range]").on("change", function() {
    line.tension(this.value / 100);
    path.attr("d", function(d, i) { return line(splines[i]); });
  });
});

d3.select(window)
    .on("mousemove", mousemove)
    .on("mouseup", mouseup);

function mouse(e) {
  return [e.pageX - rx, e.pageY - ry];
}

function mousedown() {
  m0 = mouse(d3.event);
  d3.event.preventDefault();
}

function mousemove() {
  if (m0) {
    var m1 = mouse(d3.event),
        dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI;
    div.style("-webkit-transform", "translate3d(0," + (ry - rx) + "px,0)rotate3d(0,0,0," + dm + "deg)translate3d(0," + (rx - ry) + "px,0)");
  }
}

function mouseup() {
  if (m0) {
    var m1 = mouse(d3.event),
        dm = Math.atan2(cross(m0, m1), dot(m0, m1)) * 180 / Math.PI;

    rotate += dm;
    if (rotate > 360) rotate -= 360;
    else if (rotate < 0) rotate += 360;
    m0 = null;

    div.style("-webkit-transform", "rotate3d(0,0,0,0deg)");

    svg
        .attr("transform", "translate(" + rx + "," + ry + ")rotate(" + rotate + ")")
      .selectAll("g.node text")
        .attr("dx", function(d) { return (d.x + rotate) % 360 < 180 ? 8 : -8; })
        .attr("text-anchor", function(d) { return (d.x + rotate) % 360 < 180 ? "start" : "end"; })
        .attr("transform", function(d) { return (d.x + rotate) % 360 < 180 ? null : "rotate(180)"; });
  }
}

function mouseover(d) {
  svg.selectAll("path.link.target-" + d.key)
      .classed("target", true)
      .each(updateNodes("source", true));

  svg.selectAll("path.link.source-" + d.key)
      .classed("source", true)
      .each(updateNodes("target", true));
}

function mouseout(d) {
  svg.selectAll("path.link.source-" + d.key)
      .classed("source", false)
      .each(updateNodes("target", false));

  svg.selectAll("path.link.target-" + d.key)
      .classed("target", false)
      .each(updateNodes("source", false));
}

function updateNodes(name, value) {
  return function(d) {
    if (value) this.parentNode.appendChild(this);
    svg.select("#node-" + d[name].key).classed(name, value);
  };
}

function cross(a, b) {
  return a[0] * b[1] - a[1] * b[0];
}

function dot(a, b) {
  return a[0] * b[0] + a[1] * b[1];
}

    </script>
  </body>
</html>

packages.js


(function() {
  packages = {

    // Lazily construct the package hierarchy from class names.
    root: function(classes) {
      var map = {};

      function find(name, data) {
        var node = map[name], i;
        if (!node) {
          node = map[name] = data || {name: name, children: []};
          if (name.length) {
            node.parent = find(name.substring(0, i = name.lastIndexOf(".")));
            if (!node.parent.children) node.parent.children = [];
            node.parent.children.push(node);
            node.key = name.substring(3);
          }
        }
        return node;
      }

      classes.forEach(function(d) {
        find(d.name, d);
      });

      return map[""];
    },

    // Return a list of imports for the given array of nodes.
    imports: function(nodes) {
      var map = {},
          imports = [];

      // Compute a map from name to node.
      nodes.forEach(function(d) {
        map[d.name] = d;
      });

      // For each import, construct a link from the source to target node.
      nodes.forEach(function(d) {
        if (d.imports) d.imports.forEach(function(i) {
          imports.push({source: map[d.name], target: map[i]});
        });
      });

      return imports;
    }

  };
})();

readme-d3-imports.json

[{"imports": ["d3.map"], "name": "d3.ease", "size": 2495}, {"imports": ["d3.behavior", "d3.event", "d3.selection", "d3.touches", "d3.mouse", "d3.rebind"], "name": "d3.behavior.drag", "size": 2363}, {"imports": ["d3.layout", "d3.layout.hierarchy", "d3.layout.tree"], "name": "d3.layout.pack", "size": 4980}, {"imports": ["d3.scale", "d3.interpolate", "d3.rebind", "d3.range", "d3.format", "d3.scale.nice"], "name": "d3.scale.linear", "size": 2944}, {"imports": [], "name": "d3.extent", "size": 567}, {"imports": ["d3.geo.clip", "d3.geo.circle", "d3.geo.spherical", "d3.geo.cartesian"], "name": "d3.geo.clip.circle", "size": 3480}, {"imports": ["d3.geo", "d3.geo.azimuthal", "d3.geo.projection"], "name": "d3.geo.orthographic", "size": 203}, {"imports": ["d3.transition", "d3.selection.filter"], "name": "d3.transition.filter", "size": 537}, {"imports": [], "name": "d3.ascending", "size": 87}, {"imports": ["d3.layout", "d3.layout.hierarchy", "d3.max", "d3.layout.tree"], "name": "d3.layout.cluster", "size": 2242}, {"imports": ["d3.svg.area"], "name": "d3.svg.area.radial", "size": 354}, {"imports": ["d3.time", "d3.time.day", "d3.time.year", "d3.time.interval"], "name": "d3.time.day", "size": 547}, {"imports": ["d3.geo"], "name": "d3.geo.azimuthal", "size": 561}, {"imports": ["d3.geo", "d3.geo.stream"], "name": "d3.geo.centroid", "size": 3391}, {"imports": ["d3.transition"], "name": "d3.transition.remove", "size": 191}, {"imports": ["d3.scale", "d3.range"], "name": "d3.scale.ordinal", "size": 2657}, {"imports": ["d3.transition", "d3.selection.selectAll"], "name": "d3.transition.selectAll", "size": 784}, {"imports": ["d3.geo", "d3.geo.azimuthal", "d3.geo.projection"], "name": "d3.geo.gnomonic", "size": 210}, {"imports": ["d3.time", "d3.time.day", "d3.time.year", "d3.time.interval"], "name": "d3.time.year", "size": 326}, {"imports": ["d3.geo"], "name": "d3.geo.compose", "size": 250}, {"imports": ["d3.time", "d3.time.minute", "d3.time.interval"], "name": "d3.time.minute", "size": 356}, {"imports": ["d3.layout"], "name": "d3.layout.bundle", "size": 1500}, {"imports": ["d3.selection"], "name": "d3.selection.node", "size": 244}, {"imports": ["d3.number"], "name": "d3.mean", "size": 338}, {"imports": ["d3.scale", "d3.scale.pow"], "name": "d3.scale.sqrt", "size": 70}, {"imports": ["d3.scale"], "name": "d3.scale.bilinear", "size": 212}, {"imports": ["d3.geom"], "name": "d3.geom.quadtree", "size": 3160}, {"imports": ["d3.class"], "name": "d3.map", "size": 1182}, {"imports": ["d3.selection"], "name": "d3.selection.select", "size": 793}, {"imports": ["d3.min"], "name": "d3.zip", "size": 328}, {"imports": ["d3.layout", "d3.bisect", "d3.min", "d3.max", "d3.functor"], "name": "d3.layout.histogram", "size": 3391}, {"imports": [], "name": "d3.max", "size": 458}, {"imports": ["d3.scale"], "name": "d3.scale.nice", "size": 395}, {"imports": ["d3.selection"], "name": "d3.selection.datum", "size": 153}, {"imports": ["d3.transition", "d3.selection.each"], "name": "d3.transition.each", "size": 599}, {"imports": ["d3.dispatch", "d3.event", "d3.rebind"], "name": "d3.xhr", "size": 2871}, {"imports": ["d3.time.format"], "name": "d3.time.format.locale", "size": 350}, {"imports": ["d3.geo", "d3.geo.projection"], "name": "d3.geo.equirectangular", "size": 236}, {"imports": ["d3.svg", "d3.map", "d3.functor"], "name": "d3.svg.line", "size": 11692}, {"imports": [], "name": "d3.dispatch", "size": 1436}, {"imports": [], "name": "d3.noop", "size": 22}, {"imports": ["d3.geo", "d3.rebind", "d3.geo.resample", "d3.geo.clip.circle", "d3.geo.compose", "d3.geo.rotation"], "name": "d3.geo.projection", "size": 2992}, {"imports": ["d3.selection", "d3.event"], "name": "d3.selection.on", "size": 1661}, {"imports": ["d3.behavior", "d3.event", "d3.selection", "d3.mouse", "d3.touches", "d3.rebind"], "name": "d3.behavior.zoom", "size": 5128}, {"imports": ["d3.event", "d3.dispatch"], "name": "d3.event", "size": 1705}, {"imports": ["d3.layout", "d3.sum", "d3.range"], "name": "d3.layout.pie", "size": 2739}, {"imports": ["d3.geo.path"], "name": "d3.geo.path.context", "size": 962}, {"imports": [], "name": "d3.layout", "size": 16}, {"imports": [], "name": "d3.xyz", "size": 217}, {"imports": ["d3.selection", "d3.requote", "d3.collapse"], "name": "d3.selection.classed", "size": 2552}, {"imports": [], "name": "d3.min", "size": 458}, {"imports": [], "name": "d3.nest", "size": 1806}, {"imports": ["d3.selection", "d3.selection.enter"], "name": "d3.selection.data", "size": 2908}, {"imports": ["d3.xhr"], "name": "d3.xml", "size": 140}, {"imports": ["d3.layout", "d3.layout.hierarchy"], "name": "d3.layout.partition", "size": 1109}, {"imports": ["d3.transition", "d3.ns", "d3.interpolate", "d3.transition.tween"], "name": "d3.transition.attr", "size": 1861}, {"imports": ["d3.rgb"], "name": "d3.hsl", "size": 1397}, {"imports": ["d3.selection"], "name": "d3.selection.root", "size": 547}, {"imports": ["d3.time", "d3.bisect", "d3.rebind", "d3.time.second", "d3.time.minute", "d3.time.hour", "d3.time.day", "d3.time.week", "d3.time.month", "d3.time.year", "d3.time.format", "d3.scale.linear", "d3.scale.nice"], "name": "d3.time.scale", "size": 3915}, {"imports": ["d3.geo", "d3.merge", "d3.geo.spherical"], "name": "d3.geo.clip", "size": 8472}, {"imports": ["d3.geo", "d3.geo.cartesian"], "name": "d3.geo.resample", "size": 2627}, {"imports": ["d3.geo.path", "d3.geom.polygon"], "name": "d3.geo.path.area", "size": 1000}, {"imports": ["d3.svg.diagonal"], "name": "d3.svg.diagonal.radial", "size": 583}, {"imports": ["d3.time"], "name": "d3.time.interval", "size": 1489}, {"imports": ["d3.bisect"], "name": "d3.bisect", "size": 764}, {"imports": ["d3.selection"], "name": "d3.selection.each", "size": 415}, {"imports": ["d3.scale", "d3.scale.ordinal"], "name": "d3.scale.category", "size": 1441}, {"imports": ["d3.geo"], "name": "d3.geo.spherical", "size": 265}, {"imports": ["d3.selection"], "name": "d3.selection.html", "size": 359}, {"imports": [], "name": "d3.random", "size": 668}, {"imports": ["d3.scale", "d3.scale.linear"], "name": "d3.scale.identity", "size": 603}, {"imports": ["d3.dsv"], "name": "d3.dsv.csv", "size": 34}, {"imports": ["d3.geo.clip"], "name": "d3.geo.clip.antimeridian", "size": 2793}, {"imports": ["d3.geo", "d3.geo.stream"], "name": "d3.geo.area", "size": 2065}, {"imports": ["d3.geo.azimuthal", "d3.geo", "d3.geo.projection"], "name": "d3.geo.azimuthal.equidistant", "size": 297}, {"imports": ["d3.geo.path", "d3.geom.polygon"], "name": "d3.geo.path.centroid", "size": 2246}, {"imports": ["d3.transition", "d3.selection.each"], "name": "d3.transition.tween", "size": 728}, {"imports": ["d3.compat"], "name": "d3.compat.date", "size": 62}, {"imports": ["d3.geo", "d3.geo.projection"], "name": "d3.geo.mercator", "size": 395}, {"imports": ["d3.formatPrefix", "d3.map", "d3.round"], "name": "d3.format", "size": 4227}, {"imports": ["d3.layout", "d3.permute", "d3.map", "d3.range"], "name": "d3.layout.stack", "size": 5329}, {"imports": ["d3.time", "d3.requote", "d3.map"], "name": "d3.time.format", "size": 8657}, {"imports": ["d3.geo", "d3.geo.compose"], "name": "d3.geo.rotation", "size": 1552}, {"imports": ["d3.selection"], "name": "d3.selection", "size": 961}, {"imports": ["d3.time.scale", "d3.time.format.utc", "d3.scale.linear"], "name": "d3.time.scale.utc", "size": 1415}, {"imports": [], "name": "d3.range", "size": 623}, {"imports": ["d3.svg", "d3.functor"], "name": "d3.svg.area", "size": 2683}, {"imports": [], "name": "d3.number", "size": 59}, {"imports": ["d3.transition", "d3.selection.each"], "name": "d3.transition.duration", "size": 365}, {"imports": ["d3.core"], "name": "d3.core.module", "size": 37}, {"imports": ["d3.rgb", "d3.lab"], "name": "d3.hcl", "size": 940}, {"imports": ["d3.event", "d3.mouse"], "name": "d3.touches", "size": 289}, {"imports": ["d3.xhr"], "name": "d3.html", "size": 275}, {"imports": ["d3.transition", "d3.dispatch", "d3.timer"], "name": "d3.transition", "size": 2467}, {"imports": [], "name": "d3.quantile", "size": 239}, {"imports": ["d3.geo", "d3.geo.stream"], "name": "d3.geo.bounds", "size": 753}, {"imports": [], "name": "d3.uninterpolate", "size": 278}, {"imports": ["d3.selection"], "name": "d3.selection.text", "size": 367}, {"imports": ["d3.zip"], "name": "d3.transpose", "size": 72}, {"imports": [], "name": "d3.svg", "size": 13}, {"imports": ["d3.xhr"], "name": "d3.dsv", "size": 2655}, {"imports": ["d3.time", "d3.time.second", "d3.time.interval"], "name": "d3.time.second", "size": 356}, {"imports": [], "name": "d3.round", "size": 115}, {"imports": [], "name": "d3.descending", "size": 88}, {"imports": ["d3.round", "d3.format"], "name": "d3.formatPrefix", "size": 690}, {"imports": ["d3.scale", "d3.scale.linear", "d3.format", "d3.scale.nice"], "name": "d3.scale.log", "size": 2201}, {"imports": ["d3.transition", "d3.selection.each"], "name": "d3.transition.delay", "size": 323}, {"imports": ["d3.layout", "d3.layout.hierarchy"], "name": "d3.layout.treemap", "size": 6511}, {"imports": ["d3.time", "d3.time.day", "d3.time.month", "d3.time.interval"], "name": "d3.time.month", "size": 318}, {"imports": [], "name": "d3.sum", "size": 282}, {"imports": ["d3.layout", "d3.rebind", "d3.merge"], "name": "d3.layout.hierarchy", "size": 2724}, {"imports": [], "name": "d3.array", "size": 780}, {"imports": [], "name": "d3.ns", "size": 564}, {"imports": [], "name": "d3.time", "size": 1744}, {"imports": ["d3.geo", "d3.geo.projection"], "name": "d3.geo.albers", "size": 966}, {"imports": ["d3.layout", "d3.range"], "name": "d3.layout.chord", "size": 3502}, {"imports": ["d3.time", "d3.time.hour", "d3.time.interval"], "name": "d3.time.hour", "size": 417}, {"imports": [], "name": "d3.collapse", "size": 68}, {"imports": ["d3.compat"], "name": "d3.compat.style", "size": 366}, {"imports": ["d3.selection", "d3.ascending"], "name": "d3.selection.sort", "size": 414}, {"imports": ["d3.layout", "d3.dispatch", "d3.geom.quadtree", "d3.timer", "d3.behavior.drag", "d3.event", "d3.rebind"], "name": "d3.layout.force", "size": 8853}, {"imports": [], "name": "d3.class", "size": 260}, {"imports": ["d3.time", "d3.time.day", "d3.time.year", "d3.time.week", "d3.time.interval"], "name": "d3.time.week", "size": 910}, {"imports": ["d3.selection"], "name": "d3.selection.remove", "size": 235}, {"imports": ["d3.selection"], "name": "d3.selection.property", "size": 1358}, {"imports": ["d3.transition", "d3.selection.select"], "name": "d3.transition.select", "size": 728}, {"imports": ["d3.geo.azimuthal.equal", "d3.geo", "d3.geo.azimuthal", "d3.geo.projection"], "name": "d3.geo.azimuthal.equal.area", "size": 304}, {"imports": ["d3.scale", "d3.quantile", "d3.bisect", "d3.ascending"], "name": "d3.scale.quantile", "size": 891}, {"imports": ["d3.interpolate", "d3.transform", "d3.rgb", "d3.hsl", "d3.lab", "d3.hcl"], "name": "d3.interpolate", "size": 7180}, {"imports": ["d3.geo"], "name": "d3.geo.stream", "size": 2480}, {"imports": [], "name": "d3.scale", "size": 283}, {"imports": ["d3.timer"], "name": "d3.timer", "size": 2459}, {"imports": [], "name": "d3.shuffle", "size": 184}, {"imports": ["d3.geo"], "name": "d3.geo.cartesian", "size": 889}, {"imports": ["d3.svg", "d3.scale.linear", "d3.selection", "d3.transition", "d3.scale"], "name": "d3.svg.axis", "size": 7831}, {"imports": [], "name": "d3.keys", "size": 100}, {"imports": ["d3.geo", "d3.geo.stream", "d3.geo.bounds", "d3.geo.path.context", "d3.geo.resample"], "name": "d3.geo.path", "size": 2501}, {"imports": ["d3.geom", "d3.geom.polygon", "d3.range"], "name": "d3.geom.voronoi", "size": 11309}, {"imports": ["d3.geo", "d3.geo.rotation", "d3.geo.spherical", "d3.geo.cartesian"], "name": "d3.geo.circle", "size": 2200}, {"imports": ["d3.geo"], "name": "d3.geo.haversin", "size": 68}, {"imports": [], "name": "d3.requote", "size": 129}, {"imports": [], "name": "d3.functor", "size": 118}, {"imports": [], "name": "d3.transform", "size": 1601}, {"imports": [], "name": "d3.behavior", "size": 18}, {"imports": ["d3.selection", "d3.ns"], "name": "d3.selection.attr", "size": 1932}, {"imports": ["d3.dsv"], "name": "d3.dsv.tsv", "size": 52}, {"imports": ["d3.geom", "d3.geom.voronoi"], "name": "d3.geom.delaunay", "size": 866}, {"imports": [], "name": "d3.merge", "size": 84}, {"imports": ["d3.time.format", "d3.time.format.utc"], "name": "d3.time.format.iso", "size": 473}, {"imports": ["d3.selection.enter", "d3.selection"], "name": "d3.selection.enter.select", "size": 638}, {"imports": ["d3.time.format"], "name": "d3.time.format.utc", "size": 522}, {"imports": ["d3.geom"], "name": "d3.geom.hull", "size": 2688}, {"imports": ["d3.format"], "name": "d3.format.locale", "size": 135}, {"imports": ["d3.svg", "d3.functor"], "name": "d3.svg.chord", "size": 1951}, {"imports": ["d3.selection", "d3.event"], "name": "d3.mouse", "size": 1127}, {"imports": ["d3.transition", "d3.ease", "d3.selection.each"], "name": "d3.transition.ease", "size": 308}, {"imports": [], "name": "d3.permute", "size": 174}, {"imports": ["d3.svg", "d3.map", "d3.functor"], "name": "d3.svg.symbol", "size": 2309}, {"imports": ["d3.selection", "d3.ns"], "name": "d3.selection.insert", "size": 553}, {"imports": ["d3.map", "d3.hsl", "d3.xyz", "d3.lab"], "name": "d3.rgb", "size": 7495}, {"imports": [], "name": "d3.rebind", "size": 599}, {"imports": ["d3.xhr"], "name": "d3.json", "size": 183}, {"imports": [], "name": "d3.true", "size": 38}, {"imports": ["d3.quantile", "d3.ascending"], "name": "d3.median", "size": 200}, {"imports": ["d3.geo", "d3.range"], "name": "d3.geo.graticule", "size": 1788}, {"imports": ["d3.scale"], "name": "d3.scale.quantize", "size": 720}, {"imports": ["d3.xhr"], "name": "d3.text", "size": 144}, {"imports": ["d3.svg", "d3.functor"], "name": "d3.svg.arc", "size": 2616}, {"imports": ["d3.geo", "d3.geo.interpolate"], "name": "d3.geo.greatArc", "size": 1526}, {"imports": [], "name": "d3.geo", "size": 13}, {"imports": ["d3.svg.line"], "name": "d3.svg.line.radial", "size": 467}, {"imports": [], "name": "d3.values", "size": 113}, {"imports": ["d3.selection"], "name": "d3.selection.empty", "size": 69}, {"imports": ["d3.geo", "d3.geo.azimuthal", "d3.geo.projection"], "name": "d3.geo.stereographic", "size": 269}, {"imports": [], "name": "d3.identity", "size": 40}, {"imports": ["d3.selection"], "name": "d3.selection.order", "size": 354}, {"imports": ["d3.svg", "d3.functor"], "name": "d3.svg.diagonal", "size": 894}, {"imports": [], "name": "d3.entries", "size": 136}, {"imports": ["d3.svg", "d3.selection", "d3.event", "d3.touches", "d3.mouse", "d3.rebind", "d3.scale"], "name": "d3.svg.brush", "size": 10419}, {"imports": ["d3.geo.albers", "d3.geo"], "name": "d3.geo.albers.usa", "size": 1590}, {"imports": ["d3.selection", "d3.selection.enter"], "name": "d3.selection.enter", "size": 527}, {"imports": ["d3.selection"], "name": "d3.selection.call", "size": 142}, {"imports": [], "name": "d3.color", "size": 96}, {"imports": ["d3.geom"], "name": "d3.geom.polygon", "size": 2196}, {"imports": ["d3.rgb", "d3.hcl", "d3.xyz"], "name": "d3.lab", "size": 1578}, {"imports": ["d3.geo", "d3.geo.haversin"], "name": "d3.geo.interpolate", "size": 1029}, {"imports": ["d3.scale", "d3.bisect"], "name": "d3.scale.polylinear", "size": 541}, {"imports": ["d3.transition", "d3.interpolate", "d3.transition.tween"], "name": "d3.transition.style", "size": 1919}, {"imports": ["d3.scale", "d3.bisect"], "name": "d3.scale.threshold", "size": 516}, {"imports": ["d3.selection"], "name": "d3.selection.style", "size": 2034}, {"imports": ["d3.selection", "d3.transition"], "name": "d3.selection.transition", "size": 546}, {"imports": ["d3.layout", "d3.layout.hierarchy"], "name": "d3.layout.tree", "size": 6619}, {"imports": ["d3.transition", "d3.transition.tween"], "name": "d3.transition.text", "size": 230}, {"imports": ["d3.selection", "d3.ns"], "name": "d3.selection.append", "size": 405}, {"imports": ["d3.geo.path"], "name": "d3.geo.path.buffer", "size": 1123}, {"imports": ["d3.selection"], "name": "d3.selection.filter", "size": 652}, {"imports": ["d3.scale", "d3.scale.linear", "d3.scale.nice"], "name": "d3.scale.pow", "size": 1257}, {"imports": ["d3.selection"], "name": "d3.selection.selectAll", "size": 630}, {"imports": [], "name": "d3.geom", "size": 14}]

style.css


body {
  font: 300 36px "Helvetica Neue";
  height: 640px;
  margin: 80px 160px 80px 160px;
  overflow: hidden;
  position: relative;
  width: 960px;
}

a:link, a:visited {
  color: #777;
  text-decoration: none;
}

a:hover {
  color: #666;
}

blockquote {
  margin: 0;
}

blockquote:before {
  content: "“";
  position: absolute;
  left: -.4em;
}

blockquote:after {
  content: "”";
  position: absolute;
}

body > ul {
  margin: 0;
  padding: 0;
}

h1 {
  font-size: 64px;
}

h1, h2, h3 {
  font-weight: inherit;
  margin: 0;
}

h2, h3 {
  text-align: right;
  font-size: inherit;
  position: absolute;
  bottom: 0;
  right: 0;
}

h2 {
  font-size: 24px;
  position: absolute;
}

h3 {
  bottom: -20px;
  font-size: 18px;
}

.invert {
  background: #1f1f1f;
  color: #dcdccc;
}

.invert h2, .invert h3 {
  color: #7f9f7f;
}

.string, .regexp {
  color: #f39;
}

.keyword {
  color: #00c;
}

.comment {
  color: #777;
  font-style: oblique;
}

.number {
  color: #369;
}

.class, .special {
  color: #1181B8;
}

body > svg {
  position: absolute;
  top: -80px;
  left: -160px;
}