diff --git a/sankey/README.md b/sankey/README.md index 785b8ec..85933eb 100644 --- a/sankey/README.md +++ b/sankey/README.md @@ -15,3 +15,13 @@ var sankey = d3.sankey() ``` var path = sankey.link(); ``` + +### Node attributes + +Some attributes influence how sankey does its layout (anything else is just passed through). + + * `level` can be set to an integer to specify how far right a node is pushed, starting with 0 + for the left-most position (a "source"). If unspecified, the default layout position is + "sources" left, "sinks" right, everything else to the right of their "inputs". + + diff --git a/sankey/sankey.js b/sankey/sankey.js index 380c664..33013b1 100644 --- a/sankey/sankey.js +++ b/sankey/sankey.js @@ -107,16 +107,18 @@ d3.sankey = function() { // Nodes are assigned the maximum breadth of incoming neighbors plus one; // nodes with no incoming links are assigned breadth zero, while // nodes with no outgoing links are assigned the maximum breadth. + // This can be overridden by a "level" property of the node function computeNodeBreadths() { var remainingNodes = nodes, nextNodes, - x = 0; + x = 0, maxX = 0; while (remainingNodes.length) { nextNodes = []; remainingNodes.forEach(function(node) { - node.x = x; + node.x = ('level' in node) ? node.level : x; node.dx = nodeWidth; + if (node.x > maxX){ maxX = node.x; } node.sourceLinks.forEach(function(link) { if (nextNodes.indexOf(link.target) < 0) { nextNodes.push(link.target); @@ -124,17 +126,17 @@ d3.sankey = function() { }); }); remainingNodes = nextNodes; - ++x; + x++; } - moveSinksRight(x); - scaleNodeBreadths((size[0] - nodeWidth) / (x - 1)); + moveSinksRight(maxX); + scaleNodeBreadths((size[0] - nodeWidth) / maxX); } function moveSinksRight(x) { nodes.forEach(function(node) { - if (!node.sourceLinks.length) { - node.x = x - 1; + if (!node.level && !node.sourceLinks.length) { + node.x = x; } }); }