Skip to content Skip to sidebar Skip to footer

D3 Sankey Charts - Manually Position Node Along X Axis

A problem I have come across using the d3 sankey implementation is that there's no way to specify where on the x axis a node is. I've been poking through the source and there isn't

Solution 1:

This is possible. See this JSFiddle.

enter image description here

The computeNodeBreadths function in sankey.js can be modified to look for an explicit x-position that has been assigned to a node (node.xPos):

functioncomputeNodeBreadths() {
    var remainingNodes = nodes,
        nextNodes,
        x = 0;

    while (remainingNodes.length) {
      nextNodes = [];
      remainingNodes.forEach(function(node) {

        if (node.xPos)
            node.x = node.xPos;
        else
            node.x = x;

        node.dx = nodeWidth;
        node.sourceLinks.forEach(function(link) {
          nextNodes.push(link.target);
        });
      });
      remainingNodes = nextNodes;
      ++x;
    }

    //
    moveSinksRight(x);
    scaleNodeBreadths((width - nodeWidth) / (x - 1));
  }

Then all you need to do is specify xPos on the desired nodes. In the above example I've set xPos = 1 on node2. See getData() in the JSFiddle example:

... }, {
        "node": 2,
        "name": "node2",
        "xPos": 1
    }, { ...

Solution 2:

In case anyone one will be looking for how-to fix the initial position of the deployed nodes (rects) you can do this:

sankey.layout = function(iterations) {
    computeNodeLinks();
    computeNodeValues();
    computeNodeBreadths();
    computeNodeDepths(iterations);
    computeAbsolutePositions(); // add this in sankey.js filecomputeLinkDepths();
    return sankey;
};

And add the positions themselves:

function computeAbsolutePositions() {
    nodes[0].x = 0;
    nodes[0].y = 0;
    nodes[1].x = 260;
    nodes[1].y = 0;
};

Please mind that you will have to yourself mind the positions of the rects when you hardcode them like that, as none collision check functions originally used by sankey.js are used in that example.

Hope that may help someone!

Solution 3:

Let us call the x-coordinate layer. layer=0 will be left edge, and layer=n will be the right edge. In your JSON file, in the nodes field, add the key-value pair layer: your_desired_x_as_integer.

Then go the sankey.js file and find the function componentsByBreadth.forEach. Replace the line node.x = component.x + node.x; with:

if (node.layer) node.x=node.layer;
else node.x = component.x + node.x;

You can defined density of layers like this also, e.g. nodes placed on layers 0,1,2 or 0,4,8 will have a central node and two on the edges of the width of the sankey, but 0,1,5 will not have.

If you need more help, this feature, among many other is included in my D3 Sankey app: http://sankey.csaladen.es

Solution 4:

might not be the clean answer you're after, but you can explicitly change the source and target x attributes, then update the links

http://bl.ocks.org/danharr/af796d91926d254dfe99

Post a Comment for "D3 Sankey Charts - Manually Position Node Along X Axis"