Skip to content

Commit d6a812f

Browse files
authored
Merge pull request #21562 from konewka17/fix-21561
feat(sankey): support disabling node sorting. close #21561
2 parents 7d6524e + c108d1f commit d6a812f

3 files changed

Lines changed: 112 additions & 12 deletions

File tree

src/chart/sankey/SankeySeries.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ export interface SankeySeriesOption
136136
* The number of iterations to change the position of the node
137137
*/
138138
layoutIterations?: number
139+
/**
140+
* Sorting method used when resolving node collisions within each depth column.
141+
* Set to null to preserve the original node order.
142+
*/
143+
sort?: 'desc' | null
139144

140145
nodeAlign?: 'justify' | 'left' | 'right' // TODO justify should be auto
141146

@@ -318,6 +323,7 @@ class SankeySeriesModel extends SeriesModel<SankeySeriesOption> {
318323
draggable: true,
319324

320325
layoutIterations: 32,
326+
sort: 'desc',
321327

322328
// true | false | 'move' | 'scale', see module:component/helper/RoamController.
323329
roam: false,

src/chart/sankey/sankeyLayout.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ export default function sankeyLayout(ecModel: GlobalModel, api: ExtensionAPI) {
5757
const orient = seriesModel.get('orient');
5858

5959
const nodeAlign = seriesModel.get('nodeAlign');
60+
const sort = seriesModel.get('sort');
6061

61-
layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign);
62+
layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign, sort);
6263
});
6364
}
6465

@@ -71,10 +72,11 @@ function layoutSankey(
7172
height: number,
7273
iterations: number,
7374
orient: LayoutOrient,
74-
nodeAlign: SankeySeriesOption['nodeAlign']
75+
nodeAlign: SankeySeriesOption['nodeAlign'],
76+
sort: SankeySeriesOption['sort']
7577
) {
7678
computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign);
77-
computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient);
79+
computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient, sort);
7880
computeEdgeDepths(nodes, orient);
7981
}
8082

@@ -257,6 +259,7 @@ function scaleNodeBreadths(nodes: GraphNode[], kx: number, orient: LayoutOrient)
257259
* @param nodeGap the vertical distance between two nodes
258260
* in the same column.
259261
* @param iterations the number of iterations for the algorithm
262+
* @param sort sorting method used when resolving collisions within each column
260263
*/
261264
function computeNodeDepths(
262265
nodes: GraphNode[],
@@ -265,21 +268,22 @@ function computeNodeDepths(
265268
width: number,
266269
nodeGap: number,
267270
iterations: number,
268-
orient: LayoutOrient
271+
orient: LayoutOrient,
272+
sort: SankeySeriesOption['sort']
269273
) {
270274
const nodesByBreadth = prepareNodesByBreadth(nodes, orient);
271275

272276
initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient);
273-
resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
277+
resolveCollisions(nodesByBreadth, nodeGap, height, width, orient, sort);
274278

275279
for (let alpha = 1; iterations > 0; iterations--) {
276280
// 0.99 is a experience parameter, ensure that each iterations of
277281
// changes as small as possible.
278282
alpha *= 0.99;
279283
relaxRightToLeft(nodesByBreadth, alpha, orient);
280-
resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
284+
resolveCollisions(nodesByBreadth, nodeGap, height, width, orient, sort);
281285
relaxLeftToRight(nodesByBreadth, alpha, orient);
282-
resolveCollisions(nodesByBreadth, nodeGap, height, width, orient);
286+
resolveCollisions(nodesByBreadth, nodeGap, height, width, orient, sort);
283287
}
284288
}
285289

@@ -355,13 +359,16 @@ function resolveCollisions(
355359
nodeGap: number,
356360
height: number,
357361
width: number,
358-
orient: LayoutOrient
362+
orient: LayoutOrient,
363+
sort: SankeySeriesOption['sort']
359364
) {
360365
const keyAttr = orient === 'vertical' ? 'x' : 'y';
361366
zrUtil.each(nodesByBreadth, function (nodes) {
362-
nodes.sort(function (a, b) {
363-
return a.getLayout()[keyAttr] - b.getLayout()[keyAttr];
364-
});
367+
if (sort !== null) {
368+
nodes.sort(function (a, b) {
369+
return a.getLayout()[keyAttr] - b.getLayout()[keyAttr];
370+
});
371+
}
365372
let nodeX;
366373
let node;
367374
let dy;
@@ -528,4 +535,4 @@ function computeEdgeDepths(nodes: GraphNode[], orient: LayoutOrient) {
528535
ty += edge.getLayout().dy;
529536
});
530537
});
531-
}
538+
}

test/sankey-node-sorting.html

Lines changed: 87 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)