d3 sankey charts - manually position node along x axis

纵然是瞬间 提交于 2019-11-27 14:07:43

This is possible. See this JSFiddle.

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):

  function computeNodeBreadths() {
    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
    }, { ...

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 file
    computeLinkDepths();
    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!

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

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!