block by EE2dev 00c3f65f66d807e88108

tree with embedded data

Full Screen

This tree can be used without a web server.

index.html

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

<head>
  <style>
    .node circle {
      fill: #fff;
      stroke: steelblue;
      stroke-width: 1.5px;
    }

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

    .link {
      fill: none;
      stroke: #ccc;
      stroke-width: 1.5px;   
    }
      
    .leaf {
      fill: #fff;
      stroke: steelblue;
      stroke-width: 1.5px;
    }
  </style>
  <script src="//d3js.org/d3.v3.min.js"></script>
</head>  
<body>
<div class="options">
  <button onclick="expandAll()">Expand All</button>
  <button onclick="collapseAll()">Collapse All</button>
</div>

<script>
  function getData() {
    return {
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster", "size": 3938},
      {"name": "CommunityStructure", "size": 3812},
      {"name": "MergeEdge", "size": 743}
     ]
    },
    {
     "name": "graph",
     "children": [
      {"name": "BetweennessCentrality", "size": 3534},
      {"name": "LinkDistance", "size": 5731}
     ]
    },
    {
     "name": "optimization",
     "children": [
      {"name": "AspectRatioBanker", "size": 7074}
     ]
    }
   ]
  },
  {
   "name": "animate",
   "children": [
    {"name": "Easing", "size": 17010},
    {"name": "FunctionSequence", "size": 5842},
    {
     "name": "interpolate",
     "children": [
      {"name": "ArrayInterpolator", "size": 1983},
      {"name": "ColorInterpolator", "size": 2047},
      {"name": "DateInterpolator", "size": 1375},
      {"name": "Interpolator", "size": 8746},
      {"name": "MatrixInterpolator", "size": 2202},
      {"name": "NumberInterpolator", "size": 1382},
      {"name": "ObjectInterpolator", "size": 1629},
      {"name": "PointInterpolator", "size": 1675},
      {"name": "RectangleInterpolator", "size": 2042}
     ]
    },
    {"name": "ISchedulable", "size": 1041},
    {"name": "Parallel", "size": 5176},
    {"name": "Pause", "size": 449},
    {"name": "Scheduler", "size": 5593},
    {"name": "Sequence", "size": 5534},
    {"name": "Transition", "size": 9201},
    {"name": "Transitioner", "size": 19975},
    {"name": "TransitionEvent", "size": 1116},
    {"name": "Tween", "size": 6006}
   ]
  }
 ]
}
   ;
  }
  
  var margin = {top: 20, right: 0, bottom: 20, left: 60},
      width = 1000 - margin.right - margin.left,
      height = 800 - margin.top - margin.bottom;

  var i = 0,
      duration = 750,
      root
      textinFrontOFNodeFor = [26];

  var tree = d3.layout.tree()
            .size([height, width-150])
            .separation(function(a, b) { return (a.parent == b.parent ? 1 : 3); });

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

  var svg = d3.select("body").append("svg")
      .attr("width", width + margin.right + margin.left)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

  /*
  d3.json("webTree.json", function(error, flare) {
    if (error) throw error;

    root = flare;
    root.x0 = height / 2;
    root.y0 = 0;

    root.children.forEach(collapse);
    update(root);
  });
  */
  var myData = getData();
  root = myData;
  root.x0 = height / 2;
  root.y0 = 0;

  root.children.forEach(collapse);
  update(root);

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

  function expand(d){   
      var children = (d.children)?d.children:d._children;
      if (d._children) {        
          d.children = d._children;
          d._children = null;       
      }
      if(children)
        children.forEach(expand);
  }

  function expandAll(){
      expand(root); 
      update(root);
  }

  function collapseAll(){
      root.children.forEach(collapse);
      collapse(root);
      update(root);
  }

  function collapse(d) {
      if (d.children) {
        d._children = d.children;
        d._children.forEach(collapse);
        d.children = null;
      }
    }
    
  function update(source) {
    // Compute the new tree layout.
    var nodes = tree.nodes(root).reverse(),
        links = tree.links(nodes);

    // Normalize for fixed-depth. <-- change here to change width
     nodes.forEach(function(d) { d.y = d.depth * 120; });

    // Update the nodes…
    var node = svg.selectAll("g.node")
        .data(nodes, function(d) { return d.id || (d.id = ++i); });

    // Enter any new nodes at the parent's previous position.
    var nodeEnter = node.enter().append("g")
        .attr("class", "node")
        .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
        .on("click", click);
        
    nodeEnter.each(function (d) {
      if (d.children || d._children) {
        d3.select(this).append("circle")
        .attr("r", 1e-6)
        .style("fill", "steelblue");
        }
      else  
        d3.select(this).append("rect")
          .attr("class", "leaf")
          .attr("x", -4.5)
          .attr("y", -4,5)
          .attr("width", 1e-6)
          .attr("height", 1e-6);
      });       
        
    nodeEnter.append("text").each (function (d) {
       // case: label node in front of it
       // if ((d.children || d._children) && d.depth === 4) {
       if (textinFrontOFNodeFor.indexOf(d.id) != -1) {
         d3.select(this).attr("dx", -8)
        .attr("dy", 3)
        .style("font-size", 16)
        .attr("text-anchor", "end")
        .text(d.name)
        .style("fill-opacity", 1e-6);
       }
       else {
        d3.select(this).attr("dx", (d.children || d._children) ? 0 : 8)
        .attr("dy",(d.children || d._children) ? -8 : 3)
        .style("font-size", (d.children || d._children) ? 16 : 10)
        .attr("text-anchor",(d.children || d._children) ? "middle" : "start")
        .text(d.name);
      }
    });
        
        
    // Transition nodes to their new position.
    var nodeUpdate = node.transition()
        .duration(duration)
        .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });

    nodeUpdate.select("circle")
        .attr("r", 4.5)
        .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
    
    nodeUpdate.select("rect")
          .attr("width", 9)
          .attr("height", 9);  

    nodeUpdate.select("text")
        .style("fill-opacity", 1);

    // Transition exiting nodes to the parent's new position.
    var nodeExit = node.exit().transition()
        .duration(duration)
        .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
        .remove();

    nodeExit.select("circle")
        .attr("r", 1e-6);

    nodeExit.select("text")
        .style("fill-opacity", 1e-6);

    // Update the links…
    var link = svg.selectAll("path.link")
        .data(links, function(d) { return d.target.id; });

    // Enter any new links at the parent's previous position.
    link.enter().insert("path", "g")
        .attr("class", "link")
        .attr("d", function(d) {
          var o = {x: source.x0, y: source.y0};
          return diagonal({source: o, target: o});
        });

    // Transition links to their new position.
    link.transition()
        .duration(duration)
        .attr("d", diagonal);

    // Transition exiting nodes to the parent's new position.
    link.exit().transition()
        .duration(duration)
        .attr("d", function(d) {
          var o = {x: source.x, y: source.y};
          return diagonal({source: o, target: o});
        })
        .remove();

    // Stash the old positions for transition.
    nodes.forEach(function(d) {
      d.x0 = d.x;
      d.y0 = d.y;
    });
  }

  // Toggle children on click.
  function click(d) {
    if (d.children) {
      d._children = d.children;
      d.children = null;
    } else {
      d.children = d._children;
      d._children = null;
    }
    update(d);
  }
</script>