1

I have a sankey diagram in which the user can move and position the nodes freely. I want to save the exact pixel-position selected by the user and use it in the next regeneration of the diagram.

The only way I have managed to approach this until now was to use the "x layer" of the node instead of the exact x-position (not the x-coordinate in pixels but the x-coordinate in layers/levels - 1,2,3 etc...).

Is there a way to use the pixel coordinate instead?

Cos
  • 1,649
  • 1
  • 27
  • 50
  • Could you explain precisely what happens between each "regeneration"? The solution is going to be rather different if you insert or delete nodes, etc. And if your data doesn't change too much, and you want to keep the same node positions, why let sankey move the nodes in the first place? – tarulen Mar 01 '16 at 13:39
  • The data changes a lot. Users can add and remove nodes, but should also be able to position them. So nodes have to have a fixed position. This is why I think the transform proposition below would not work, since adding a new node is not taken into account and the existing nodes with transforms will be moved to a saved position that doesn't fit in the new arrangement. – Cos Mar 02 '16 at 15:49
  • How would you go on about inserting a node in a sankey graph when all the rest have fixed positions? Sankey is designed to build a layout from scratch, so you'd basically end up editing the whole Sankey file. Why not use Sankey for the first layout, then a force diagram to place new nodes (where every old node is fixed)? – tarulen Mar 02 '16 at 15:56

3 Answers3

0

I guess you're using transform when the user moves the nodes.

If you assign each node an id, you could save pairs like [ (#id, transformation) ..; ] and apply it again after.

I could try something if you show your code :)

pltrdy
  • 2,069
  • 1
  • 11
  • 29
  • Hey pltrdy, I'm using a code similar to the accepted answer here http://stackoverflow.com/questions/21539265/d3-sankey-charts-manually-position-node-along-x-axis?rq=1 At the moment I'm using the 'xPos' attribute for a node to position it on the x-axis, but it's not sufficiently accurate. I'm curious if the transform idea would work well when new nodes are added or existing nodes are removed. For this, the transformation should not be relative to the node's position, but instead bring the node to a fixed coordinate. I hope this makes sense. – Cos Mar 02 '16 at 15:53
  • Hello pltrdy, I awarded you the bounty for the idea, but I sadly didn't have time to talk to you in more detail about it. Would you be so kind to help me follow this line of thought a bit further these days? – Cos Mar 04 '16 at 13:29
  • sure, was a bit busy. I'll be back to you asap ;) And thx for the bounty! – pltrdy Mar 04 '16 at 16:44
  • You definitely should make a jsfiddle, then we could practically discuss your issue. I could only speak about the idea just because I dont have access to your code. I guess I won't be able to give better anwser without code – pltrdy Mar 08 '16 at 08:33
  • Hi pltrdy, do you have any means of communication outside Stackoverflow? – Cos May 18 '16 at 15:13
0

The sankey plugin acts as your data model. All it does is calculations of x for the 'rect's and 'dx' for the paths and many other position calculations. You can capture those positions with the 'dragend'.

Once you have the data you can get and set with pattern

var getNodes = sankey.nodes();
//do something here to set the position 
sankey.nodes(getNodes);

Then you would doe the same with the links. Then recalculate everything.

sankey.layout() 

Without seeing your code I am sure there will bet another step to make sure this works, but you will find it is an easy module to update.

You might want to check the actual source code because I have a custom version that might have different variable names, but it works the same.

jamesRH
  • 420
  • 3
  • 12
0

You can extract the x and y values and save them into an array as follows:

var savedCoordinates = sankey.nodes().map(function(d) {
        return {x:d.x, y:d.y};
});

Of course, this must be used after the layout has been computed, otherwise x andy values are undefined.

To return to your saved coordinates, you can use the following:

sankey.nodes().forEach( function(d,i) {
      d.x= savedCoordinates[i].x;
      d.y= savedCoordinates[i].y;
});

Finally, you'll need to update the drawing with whichever drawing function you are using (updating the transform attributes of g nodes and the path attributes for the links).

PS: You notice that I'm assuming the node order doesn't change. If it does, you need to provide an id field, or similar to your data... do you have one?

tarulen
  • 2,070
  • 9
  • 14