block by micahstubbs 5e07b8b42f4fb826a7145e800dc23ec2

Bounded Force Layout - Columns by Depth

Full Screen

This example takes bjtucker‘s block: Bounded Force Layout - force rank by group and swaps out the dataset, showing energy flows from source to use.

This example also adds a Simple D3 tooltip. Hat tip to biovisualize for that bl.ock.

See another view of this energy flow data at the bl.ock Sankey Particles - Transparent Links


README.md from the original bl.ock


This D3 example shows how to constrain the position of nodes within the rectangular bounds of the containing SVG element. As a side-effect of updating the node’s cx and cy attributes, we update the node positions to be within the range [radius, width - radius] for x, [radius, height - radius] for y. If you prefer, you could use the each operator to do this as a separate step, rather than as a side-effect of setting attributes.

Wrote the each operator step described above, but used tick to settle groups into separate ranks. -bjtucker

index.html

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

circle {
  stroke-width: 1.5px;
}

line {
  stroke: #999;
}

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

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

var fill = d3.scale.category20();

var force = d3.layout.force()
    .gravity(0.05)
    .charge(-50) // -50
    .linkDistance(50)
    .size([width, height])
    .linkStrength(0.005)
    .friction(0.9)
    .theta(0.8)
    .alpha(0.1)

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

svg.append('rect')
  .attr("width", width)
  .attr("height", height)
  .style({
    fill: 'none',
    stroke: 'none',
    'stroke-width': 1
  });

d3.json("graph.json", function(error, graph) {
  if (error) throw error;
  
  var tooltip = d3.select("body")
		.append("div")
		.style("position", "absolute")
		.style("z-index", "10")
		.style("visibility", "hidden");
  
  var link = svg.selectAll("line")
      .data(graph.links)
    .enter().append("line");

  var node = svg.selectAll("circle")
      .data(graph.nodes)
    .enter().append("circle")
      .attr("r", radius - .75)
      .style("fill", function(d) { return fill(d.depth); })
      .style("stroke", function(d) { return d3.rgb(fill(d.group)).darker(); })
      .call(force.drag);

  force
      .nodes(graph.nodes)
      .links(graph.links)
      .on("tick", tick)
      .start();

  function tick() {

    node.each(function(d) { w = 105 * (1 + d.depth); d.x -= (0.2 * (d.x - w)) })

    node.attr("cx", function(d) {return d.x = Math.max(radius, Math.min(width - radius, d.x)); })
        .attr("cy", function(d) {return d.y = Math.max(radius, Math.min(height - radius, d.y)); });
        

    link.attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });
  }
  
  node
    .on("mouseover", function(d){
    	return tooltip
      	.text(d.name)
        .style("visibility", "visible");
  	})
		.on("mousemove", function(){
    	return tooltip
      	.style("top", (event.pageY - 10) + "px")
        .style("left",(event.pageX + 10) + "px");
  	})
		.on("mouseout", function(){
    	return tooltip
        .style("visibility", "hidden")
  	});
});

</script>

graph.json

{  
   "nodes":[  
      {  
         "name":"Agricultural 'waste'",
         "depth": 0
      },
      {  
         "name":"Bio-conversion",
         "depth": 1
      },
      {  
         "name":"Liquid",
         "depth": 2
      },
      {  
         "name":"Losses",
         "depth": 7
      },
      {  
         "name":"Solid",
         "depth": 2
      },
      {  
         "name":"Gas",
         "depth": 2
      },
      {  
         "name":"Biofuel imports",
         "depth": 0
      },
      {  
         "name":"Biomass imports",
         "depth": 0
      },
      {  
         "name":"Coal imports",
         "depth": 0
      },
      {  
         "name":"Coal",
         "depth": 1
      },
      {  
         "name":"Coal reserves",
         "depth": 0
      },
      {  
         "name":"District heating",
         "depth": 4
      },
      {  
         "name":"Industry",
         "depth": 7
      },
      {  
         "name":"Heating and cooling - commercial",
         "depth": 7
      },
      {  
         "name":"Heating and cooling - homes",
         "depth": 7
      },
      {  
         "name":"Electricity grid",
         "depth": 4
      },
      {  
         "name":"Over generation / exports",
         "depth": 7
      },
      {  
         "name":"H2 conversion",
         "depth": 5
      },
      {  
         "name":"Road transport",
         "depth": 7
      },
      {  
         "name":"Agriculture",
         "depth": 7
      },
      {  
         "name":"Rail transport",
         "depth": 7
      },
      {  
         "name":"Lighting & appliances - commercial",
         "depth": 7
      },
      {  
         "name":"Lighting & appliances - homes",
         "depth": 7
      },
      {  
         "name":"Gas imports",
         "depth": 0
      },
      {  
         "name":"Ngas",
         "depth": 1
      },
      {  
         "name":"Gas reserves",
         "depth": 0
      },
      {  
         "name":"Thermal generation",
         "depth": 3
      },
      {  
         "name":"Geothermal",
         "depth": 0
      },
      {  
         "name":"H2",
         "depth": 6
      },
      {  
         "name":"Hydro",
         "depth": 0
      },
      {  
         "name":"International shipping",
         "depth": 7
      },
      {  
         "name":"Domestic aviation",
         "depth": 7
      },
      {  
         "name":"International aviation",
         "depth": 7
      },
      {  
         "name":"National navigation",
         "depth": 7
      },
      {  
         "name":"Marine algae",
         "depth": 0
      },
      {  
         "name":"Nuclear",
         "depth": 0
      },
      {  
         "name":"Oil imports",
         "depth": 0
      },
      {  
         "name":"Oil",
         "depth": 1
      },
      {  
         "name":"Oil reserves",
         "depth": 0
      },
      {  
         "name":"Other waste",
         "depth": 0
      },
      {  
         "name":"Pumped heat",
         "depth": 0
      },
      {  
         "name":"Solar PV",
         "depth": 1
      },
      {  
         "name":"Solar Thermal",
         "depth": 1
      },
      {  
         "name":"Solar",
         "depth": 0
      },
      {  
         "name":"Tidal",
         "depth": 0
      },
      {  
         "name":"UK land based bioenergy",
         "depth": 0
      },
      {  
         "name":"Wave",
         "depth": 0
      },
      {  
         "name":"Wind",
         "depth": 0
      }
   ],
   "links":[  
      {  
         "source":0,
         "target":1,
         "value":124.729
      },
      {  
         "source":1,
         "target":2,
         "value":0.597
      },
      {  
         "source":1,
         "target":3,
         "value":26.862
      },
      {  
         "source":1,
         "target":4,
         "value":280.322
      },
      {  
         "source":1,
         "target":5,
         "value":81.144
      },
      {  
         "source":6,
         "target":2,
         "value":35
      },
      {  
         "source":7,
         "target":4,
         "value":35
      },
      {  
         "source":8,
         "target":9,
         "value":11.606
      },
      {  
         "source":10,
         "target":9,
         "value":63.965
      },
      {  
         "source":9,
         "target":4,
         "value":75.571
      },
      {  
         "source":11,
         "target":12,
         "value":10.639
      },
      {  
         "source":11,
         "target":13,
         "value":22.505
      },
      {  
         "source":11,
         "target":14,
         "value":46.184
      },
      {  
         "source":15,
         "target":16,
         "value":104.453
      },
      {  
         "source":15,
         "target":14,
         "value":113.726
      },
      {  
         "source":15,
         "target":17,
         "value":27.14
      },
      {  
         "source":15,
         "target":12,
         "value":342.165
      },
      {  
         "source":15,
         "target":18,
         "value":37.797
      },
      {  
         "source":15,
         "target":19,
         "value":4.412
      },
      {  
         "source":15,
         "target":13,
         "value":40.858
      },
      {  
         "source":15,
         "target":3,
         "value":56.691
      },
      {  
         "source":15,
         "target":20,
         "value":7.863
      },
      {  
         "source":15,
         "target":21,
         "value":90.008
      },
      {  
         "source":15,
         "target":22,
         "value":93.494
      },
      {  
         "source":23,
         "target":24,
         "value":40.719
      },
      {  
         "source":25,
         "target":24,
         "value":82.233
      },
      {  
         "source":5,
         "target":13,
         "value":0.129
      },
      {  
         "source":5,
         "target":3,
         "value":1.401
      },
      {  
         "source":5,
         "target":26,
         "value":151.891
      },
      {  
         "source":5,
         "target":19,
         "value":2.096
      },
      {  
         "source":5,
         "target":12,
         "value":48.58
      },
      {  
         "source":27,
         "target":15,
         "value":7.013
      },
      {  
         "source":17,
         "target":28,
         "value":20.897
      },
      {  
         "source":17,
         "target":3,
         "value":6.242
      },
      {  
         "source":28,
         "target":18,
         "value":20.897
      },
      {  
         "source":29,
         "target":15,
         "value":6.995
      },
      {  
         "source":2,
         "target":12,
         "value":121.066
      },
      {  
         "source":2,
         "target":30,
         "value":128.69
      },
      {  
         "source":2,
         "target":18,
         "value":135.835
      },
      {  
         "source":2,
         "target":31,
         "value":14.458
      },
      {  
         "source":2,
         "target":32,
         "value":206.267
      },
      {  
         "source":2,
         "target":19,
         "value":3.64
      },
      {  
         "source":2,
         "target":33,
         "value":33.218
      },
      {  
         "source":2,
         "target":20,
         "value":4.413
      },
      {  
         "source":34,
         "target":1,
         "value":4.375
      },
      {  
         "source":24,
         "target":5,
         "value":122.952
      },
      {  
         "source":35,
         "target":26,
         "value":839.978
      },
      {  
         "source":36,
         "target":37,
         "value":504.287
      },
      {  
         "source":38,
         "target":37,
         "value":107.703
      },
      {  
         "source":37,
         "target":2,
         "value":611.99
      },
      {  
         "source":39,
         "target":4,
         "value":56.587
      },
      {  
         "source":39,
         "target":1,
         "value":77.81
      },
      {  
         "source":40,
         "target":14,
         "value":193.026
      },
      {  
         "source":40,
         "target":13,
         "value":70.672
      },
      {  
         "source":41,
         "target":15,
         "value":59.901
      },
      {  
         "source":42,
         "target":14,
         "value":19.263
      },
      {  
         "source":43,
         "target":42,
         "value":19.263
      },
      {  
         "source":43,
         "target":41,
         "value":59.901
      },
      {  
         "source":4,
         "target":19,
         "value":0.882
      },
      {  
         "source":4,
         "target":26,
         "value":400.12
      },
      {  
         "source":4,
         "target":12,
         "value":46.477
      },
      {  
         "source":26,
         "target":15,
         "value":525.531
      },
      {  
         "source":26,
         "target":3,
         "value":787.129
      },
      {  
         "source":26,
         "target":11,
         "value":79.329
      },
      {  
         "source":44,
         "target":15,
         "value":9.452
      },
      {  
         "source":45,
         "target":1,
         "value":182.01
      },
      {  
         "source":46,
         "target":15,
         "value":19.013
      },
      {  
         "source":47,
         "target":15,
         "value":289.366
      }
   ]
}