Skip to content

Commit 789ae0c

Browse files
author
wfr
committed
Reset original node label layout in vertical case; adjust select.js; add mocks for link and node sort with reverse
1 parent f89f62f commit 789ae0c

8 files changed

Lines changed: 226 additions & 13 deletions

src/traces/sankey/render.js

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1067,9 +1067,9 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
10671067
svgTextUtils.convertToTspans(e, gd);
10681068
})
10691069
.attr('text-anchor', function(d) {
1070-
// vertical: labels are centered over the node. horizontal: aligned to the outer
1071-
// edge (reverse mirrors the layout, so the outer side and anchor flip).
1072-
if(!d.horizontal) return 'middle';
1070+
// horizontal: aligned to the outer edge (reverse flips which side is outer).
1071+
// vertical: inside-node placement, anchored at 'start'.
1072+
if(!d.horizontal) return 'start';
10731073
return (d.left !== d.reverse) ? 'end' : 'start';
10741074
})
10751075
.attr('transform', function(d) {
@@ -1083,12 +1083,18 @@ module.exports = function(gd, svg, calcData, layout, callbacks) {
10831083
var pad = d.nodeLineWidth / 2 + TEXTPAD;
10841084

10851085
if(!d.horizontal) {
1086-
var posY = d.visibleHeight / 2;
1087-
// last Column (originalLayer === 1): put label towards center.
1088-
var posX = d.reverse ?
1089-
(d.left ? -(pad + CAP_SHIFT * d.textFont.size) : (d.visibleWidth + pad)) : (d.left ? -pad : (d.visibleWidth + pad + CAP_SHIFT * d.textFont.size));
1086+
// vertical: label sits inside the node, centered along its length.
1087+
// forward's local flip (scale(-1,1) + rotate(90)) is a reflection,
1088+
// reverse's (rotate(90) alone) a pure rotation; the group
1089+
// matrix has the same opposing handedness. That flips the sign with which
1090+
// the CAP_SHIFT baseline correction (baked into blockHeight) lands on
1091+
// screen, so it must be applied with the opposite sign for reverse -
1092+
// otherwise the label renders about half a line height too high.
1093+
var posY = d.reverse
1094+
? (d.visibleWidth + blockHeight) / 2
1095+
: (d.visibleWidth - blockHeight) / 2;
10901096
var flipV = d.reverse ? strRotate(90) : ('scale(-1,1)' + strRotate(90));
1091-
return strTranslate(posX, posY) + flipV;
1097+
return strTranslate(posY, pad) + flipV;
10921098
}
10931099

10941100
// horizontal: center along the node length, place just past the thickness edge.

src/traces/sankey/select.js

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,30 @@ module.exports = function selectPoints(searchInfo, selectionTester) {
55
var selection = [];
66
var fullData = cd[0].trace;
77

8-
var nodes = fullData._sankey.graph.nodes;
8+
var model = fullData._sankey;
9+
var nodes = model.graph.nodes;
10+
var vertical = fullData.orientation === 'v';
11+
var reverse = fullData.direction === 'reverse';
912

1013
for(var i = 0; i < nodes.length; i++) {
1114
var node = nodes[i];
1215
if(node.partOfGroup) continue; // Those are invisible
1316

14-
// Position of node's centroid
15-
var pos = [(node.x0 + node.x1) / 2, (node.y0 + node.y1) / 2];
17+
// Position of node's centroid in the layout frame
18+
var cx = (node.x0 + node.x1) / 2;
19+
var cy = (node.y0 + node.y1) / 2;
1620

17-
// Swap x and y if trace is vertical
18-
if(fullData.orientation === 'v') pos.reverse();
21+
// Mirror/swap to match the group transform applied in render.js (sankeyTransform):
22+
// h + forward: (cx, cy)
23+
// h + reverse: (width - cx, cy) -> matrix(-1 0 0 1) + translate(width, 0)
24+
// v + forward: (cy, cx) -> matrix( 0 1 1 0) (swap x/y)
25+
// v + reverse: (cy, height - cx) -> matrix( 0 -1 1 0) + translate(0, height)
26+
var pos;
27+
if(vertical) {
28+
pos = [cy, reverse ? model.height - cx : cx];
29+
} else {
30+
pos = [reverse ? model.width - cx : cx, cy];
31+
}
1932

2033
if(selectionTester && selectionTester.contains(pos, false, i, searchInfo)) {
2134
selection.push({
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"data": [
3+
{
4+
"type": "sankey",
5+
"direction": "reverse",
6+
"node": {
7+
"label": ["0", "1", "2", "3", "4", "5"],
8+
"align": "center",
9+
"color": "gray"
10+
},
11+
"link": {
12+
"source": [0, 0, 0, 0, 1, 4],
13+
"target": [1, 3, 2, 4, 5, 5],
14+
"value": [1, 1, 2, 1, 1, 1],
15+
"color": [
16+
"rgba(230, 25, 75, 0.6)",
17+
"rgba(255, 165, 0, 0.6)",
18+
"rgba(60, 180, 75, 0.6)",
19+
"rgba(0, 130, 200, 0.6)",
20+
"rgba(145, 30, 180, 0.6)",
21+
"rgba(128, 128, 128, 0.6)"
22+
],
23+
"sort": "input"
24+
}
25+
}
26+
],
27+
"layout": {
28+
"title": { "text": "Sankey with link ordering matching the input array" },
29+
"width": 800,
30+
"height": 800
31+
}
32+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"data": [
3+
{
4+
"type": "sankey",
5+
"orientation": "v",
6+
"direction": "reverse",
7+
"node": {
8+
"label": ["0", "1", "2", "3", "4", "5"],
9+
"align": "center",
10+
"color": "gray"
11+
},
12+
"link": {
13+
"source": [0, 0, 0, 0, 1, 4],
14+
"target": [1, 3, 2, 4, 5, 5],
15+
"value": [1, 1, 2, 1, 1, 1],
16+
"color": [
17+
"rgba(230, 25, 75, 0.6)",
18+
"rgba(255, 165, 0, 0.6)",
19+
"rgba(60, 180, 75, 0.6)",
20+
"rgba(0, 130, 200, 0.6)",
21+
"rgba(145, 30, 180, 0.6)",
22+
"rgba(128, 128, 128, 0.6)"
23+
],
24+
"sort": "input"
25+
}
26+
}
27+
],
28+
"layout": {
29+
"title": { "text": "Sankey with link ordering matching the input array" },
30+
"width": 800,
31+
"height": 800
32+
}
33+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"data": [
3+
{
4+
"type": "sankey",
5+
"orientation": "v",
6+
"node": {
7+
"label": ["0", "1", "2", "3", "4", "5"],
8+
"align": "center",
9+
"color": "gray"
10+
},
11+
"link": {
12+
"source": [0, 0, 0, 0, 1, 4],
13+
"target": [1, 3, 2, 4, 5, 5],
14+
"value": [1, 1, 2, 1, 1, 1],
15+
"color": [
16+
"rgba(230, 25, 75, 0.6)",
17+
"rgba(255, 165, 0, 0.6)",
18+
"rgba(60, 180, 75, 0.6)",
19+
"rgba(0, 130, 200, 0.6)",
20+
"rgba(145, 30, 180, 0.6)",
21+
"rgba(128, 128, 128, 0.6)"
22+
],
23+
"sort": "input"
24+
}
25+
}
26+
],
27+
"layout": {
28+
"title": { "text": "Sankey with link ordering matching the input array" },
29+
"width": 800,
30+
"height": 800
31+
}
32+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"data": [
3+
{
4+
"type": "sankey",
5+
"direction": "reverse",
6+
"node": {
7+
"label": ["0", "1", "2", "3", "4", "5"],
8+
"align": "center",
9+
"color": "gray",
10+
"sort": "input"
11+
},
12+
"link": {
13+
"source": [0, 0, 0, 0, 1, 4],
14+
"target": [1, 3, 2, 4, 5, 5],
15+
"value": [1, 1, 2, 1, 1, 1],
16+
"color": [
17+
"rgba(230, 25, 75, 0.6)",
18+
"rgba(255, 165, 0, 0.6)",
19+
"rgba(60, 180, 75, 0.6)",
20+
"rgba(0, 130, 200, 0.6)",
21+
"rgba(145, 30, 180, 0.6)",
22+
"rgba(128, 128, 128, 0.6)"
23+
]
24+
}
25+
}
26+
],
27+
"layout": {
28+
"title": { "text": "Sankey with vertical node ordering matching the input array" },
29+
"width": 800,
30+
"height": 800
31+
}
32+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"data": [
3+
{
4+
"type": "sankey",
5+
"orientation": "v",
6+
"direction": "reverse",
7+
"node": {
8+
"label": ["0", "1", "2", "3", "4", "5"],
9+
"align": "center",
10+
"color": "gray",
11+
"sort": "input"
12+
},
13+
"link": {
14+
"source": [0, 0, 0, 0, 1, 4],
15+
"target": [1, 3, 2, 4, 5, 5],
16+
"value": [1, 1, 2, 1, 1, 1],
17+
"color": [
18+
"rgba(230, 25, 75, 0.6)",
19+
"rgba(255, 165, 0, 0.6)",
20+
"rgba(60, 180, 75, 0.6)",
21+
"rgba(0, 130, 200, 0.6)",
22+
"rgba(145, 30, 180, 0.6)",
23+
"rgba(128, 128, 128, 0.6)"
24+
]
25+
}
26+
}
27+
],
28+
"layout": {
29+
"title": { "text": "Sankey with vertical node ordering matching the input array" },
30+
"width": 800,
31+
"height": 800
32+
}
33+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"data": [
3+
{
4+
"type": "sankey",
5+
"orientation": "v",
6+
"node": {
7+
"label": ["0", "1", "2", "3", "4", "5"],
8+
"align": "center",
9+
"color": "gray",
10+
"sort": "input"
11+
},
12+
"link": {
13+
"source": [0, 0, 0, 0, 1, 4],
14+
"target": [1, 3, 2, 4, 5, 5],
15+
"value": [1, 1, 2, 1, 1, 1],
16+
"color": [
17+
"rgba(230, 25, 75, 0.6)",
18+
"rgba(255, 165, 0, 0.6)",
19+
"rgba(60, 180, 75, 0.6)",
20+
"rgba(0, 130, 200, 0.6)",
21+
"rgba(145, 30, 180, 0.6)",
22+
"rgba(128, 128, 128, 0.6)"
23+
]
24+
}
25+
}
26+
],
27+
"layout": {
28+
"title": { "text": "Sankey with vertical node ordering matching the input array" },
29+
"width": 800,
30+
"height": 800
31+
}
32+
}

0 commit comments

Comments
 (0)