block by nitaku 2d502924bad6152acbe5

Basic treemap (flare)

Full Screen

A reference example for implementing treemaps in D3.js, showing the flare software package hierarchy.

This example is intentionally basic, and it lacks many important features such as labels or interaction.

index.js

(function() {
  var PADDING, SCALE, TIP, height, svg, treemap, vis, width, zoom, zoomable_layer;

  SCALE = 400;

  PADDING = 8;

  TIP = 10;

  treemap = d3.layout.treemap().size([SCALE, SCALE]).value(function(node) {
    return node.size;
  });

  svg = d3.select('svg');

  width = svg.node().getBoundingClientRect().width;

  height = svg.node().getBoundingClientRect().height;

  svg.attr({
    viewBox: "" + (-width / 2) + " " + (-height / 2) + " " + width + " " + height
  });

  zoomable_layer = svg.append('g');

  zoom = d3.behavior.zoom().scaleExtent([1, 10]).on('zoom', function() {
    return zoomable_layer.attr({
      transform: "translate(" + (zoom.translate()) + ")scale(" + (zoom.scale()) + ")"
    });
  });

  svg.call(zoom);

  vis = zoomable_layer.append('g').attr({
    transform: "translate(" + (-SCALE / 2) + "," + (-SCALE / 2) + ")"
  });

  d3.json('http://wafi.iit.cnr.it/webvis/tmp/flare.json', function(tree) {
    var enter_nodes, nodes, nodes_data;

    nodes_data = treemap.nodes(tree);
    nodes = vis.selectAll('.node').data(nodes_data);
    enter_nodes = nodes.enter().insert('rect', 'rect').attr({
      "class": 'node',
      x: function(node) {
        return node.x;
      },
      y: function(node) {
        return node.y;
      },
      width: function(node) {
        return node.dx;
      },
      height: function(node) {
        return node.dy;
      },
      stroke: function(node) {
        switch (node.depth) {
          case 0:
            return '#333';
          case 1:
            return '#999';
          default:
            return '#DDD';
        }
      },
      'stroke-width': function(node) {
        switch (node.depth) {
          case 0:
            return 3;
          case 1:
            return 2;
          default:
            return 1;
        }
      }
    });
    return enter_nodes.append('title').text(function(node) {
      return node.name;
    });
  });

}).call(this);

index.html

<!DOCTYPE html>
<html>
	<head>
        <meta charset="utf-8">
        <meta name="description" content="Basic treemap (flare)" />
        <title>Basic treemap (flare)</title>
		<link type="text/css" href="index.css" rel="stylesheet"/>
        <script src="//d3js.org/d3.v3.min.js"></script>
	</head>
	<body>
        <svg height="500" width="960"></svg>
        <script src="index.js"></script>
	</body>
</html>

index.coffee

# layout, behaviors and scales
SCALE = 400
PADDING = 8
TIP = 10

treemap = d3.layout.treemap()
  .size([SCALE, SCALE])
  .value((node) -> node.size)
  
svg = d3.select('svg')
width = svg.node().getBoundingClientRect().width
height = svg.node().getBoundingClientRect().height

# translate the viewBox to have (0,0) at the center of the vis
svg
  .attr
    viewBox: "#{-width/2} #{-height/2} #{width} #{height}"
    
# append a group for zoomable content
zoomable_layer = svg.append('g')
 
# define a zoom behavior
zoom = d3.behavior.zoom()
  .scaleExtent([1,10]) # min-max zoom
  .on 'zoom', () ->
    # GEOMETRIC ZOOM
    zoomable_layer
      .attr
        transform: "translate(#{zoom.translate()})scale(#{zoom.scale()})"

# bind the zoom behavior to the main SVG
svg.call(zoom)

# group the visualization
vis = zoomable_layer.append('g')
  .attr
    transform: "translate(#{-SCALE/2},#{-SCALE/2})"

    
d3.json 'http://wafi.iit.cnr.it/webvis/tmp/flare.json', (tree) ->
  nodes_data = treemap.nodes(tree)
  
  nodes = vis.selectAll('.node')
    .data(nodes_data)
    
  enter_nodes = nodes.enter().insert('rect','rect')
    .attr
      class: 'node'
      x: (node) -> node.x
      y: (node) -> node.y
      width: (node) -> node.dx
      height: (node) -> node.dy
      stroke: (node) ->
        switch node.depth
          when 0 then '#333'
          when 1 then '#999'
          else '#DDD'
      'stroke-width': (node) ->
        switch node.depth
          when 0 then 3
          when 1 then 2
          else 1
  
  enter_nodes.append('title')
    .text((node) -> node.name)
    
  

index.css

svg {
  background: white;
}
.node {
  shape-rendering: crispEdges;
  vector-effect: non-scaling-stroke;
  fill: none;
}
.label {
  text-anchor: middle;
  font-family: sans-serif;
  /*text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;*/
  text-shadow: -2px 0 white, 0 2px white, 2px 0 white, 0 -2px white, -1px -1px white, 1px -1px white, 1px 1px white, -1px 1px white;
}