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 really a "clean" way to specify the x value on a reasonable scale (ie, 1-5 where the chart is 5 nodes wide). I am creating something that can be used like a course planner for education, so the x value will correspond with the semester. Supposing I had a course I couldn't take until my sophomore year of college, this would be at an x of 3 (1/2 are freshman, 3/4 sophomore, etc). The problem is, if there is nothing that links to this course beforehand, it will always be at an x of 1, so I would like to push it to the right two spaces.
I have noticed that the x value in the actual sankey chart does not reflect how many nodes across it is, so this is a bit difficult to do.
I've also come across this question, and I realize that by default the chart will not let me position a node. I have no problems tweaking the sankey.js example to accomplish this, but I'm stuck as to how to do so, currently.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With