diff --git a/src/chart/sankey/SankeySeries.ts b/src/chart/sankey/SankeySeries.ts index ebd85227ab..590d5a6205 100644 --- a/src/chart/sankey/SankeySeries.ts +++ b/src/chart/sankey/SankeySeries.ts @@ -136,6 +136,11 @@ export interface SankeySeriesOption * The number of iterations to change the position of the node */ layoutIterations?: number + /** + * Sorting method used when resolving node collisions within each depth column. + * Set to null to preserve the original node order. + */ + sort?: 'desc' | null nodeAlign?: 'justify' | 'left' | 'right' // TODO justify should be auto @@ -318,6 +323,7 @@ class SankeySeriesModel extends SeriesModel { draggable: true, layoutIterations: 32, + sort: 'desc', // true | false | 'move' | 'scale', see module:component/helper/RoamController. roam: false, diff --git a/src/chart/sankey/sankeyLayout.ts b/src/chart/sankey/sankeyLayout.ts index 8e9c8d22bb..a75388b1dd 100644 --- a/src/chart/sankey/sankeyLayout.ts +++ b/src/chart/sankey/sankeyLayout.ts @@ -57,8 +57,9 @@ export default function sankeyLayout(ecModel: GlobalModel, api: ExtensionAPI) { const orient = seriesModel.get('orient'); const nodeAlign = seriesModel.get('nodeAlign'); + const sort = seriesModel.get('sort'); - layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign); + layoutSankey(nodes, edges, nodeWidth, nodeGap, width, height, iterations, orient, nodeAlign, sort); }); } @@ -71,10 +72,11 @@ function layoutSankey( height: number, iterations: number, orient: LayoutOrient, - nodeAlign: SankeySeriesOption['nodeAlign'] + nodeAlign: SankeySeriesOption['nodeAlign'], + sort: SankeySeriesOption['sort'] ) { computeNodeBreadths(nodes, edges, nodeWidth, width, height, orient, nodeAlign); - computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient); + computeNodeDepths(nodes, edges, height, width, nodeGap, iterations, orient, sort); computeEdgeDepths(nodes, orient); } @@ -257,6 +259,7 @@ function scaleNodeBreadths(nodes: GraphNode[], kx: number, orient: LayoutOrient) * @param nodeGap the vertical distance between two nodes * in the same column. * @param iterations the number of iterations for the algorithm + * @param sort sorting method used when resolving collisions within each column */ function computeNodeDepths( nodes: GraphNode[], @@ -265,21 +268,22 @@ function computeNodeDepths( width: number, nodeGap: number, iterations: number, - orient: LayoutOrient + orient: LayoutOrient, + sort: SankeySeriesOption['sort'] ) { const nodesByBreadth = prepareNodesByBreadth(nodes, orient); initializeNodeDepth(nodesByBreadth, edges, height, width, nodeGap, orient); - resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient, sort); for (let alpha = 1; iterations > 0; iterations--) { // 0.99 is a experience parameter, ensure that each iterations of // changes as small as possible. alpha *= 0.99; relaxRightToLeft(nodesByBreadth, alpha, orient); - resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient, sort); relaxLeftToRight(nodesByBreadth, alpha, orient); - resolveCollisions(nodesByBreadth, nodeGap, height, width, orient); + resolveCollisions(nodesByBreadth, nodeGap, height, width, orient, sort); } } @@ -355,13 +359,16 @@ function resolveCollisions( nodeGap: number, height: number, width: number, - orient: LayoutOrient + orient: LayoutOrient, + sort: SankeySeriesOption['sort'] ) { const keyAttr = orient === 'vertical' ? 'x' : 'y'; zrUtil.each(nodesByBreadth, function (nodes) { - nodes.sort(function (a, b) { - return a.getLayout()[keyAttr] - b.getLayout()[keyAttr]; - }); + if (sort !== null) { + nodes.sort(function (a, b) { + return a.getLayout()[keyAttr] - b.getLayout()[keyAttr]; + }); + } let nodeX; let node; let dy; @@ -528,4 +535,4 @@ function computeEdgeDepths(nodes: GraphNode[], orient: LayoutOrient) { ty += edge.getLayout().dy; }); }); -} \ No newline at end of file +} diff --git a/test/sankey-node-sorting.html b/test/sankey-node-sorting.html new file mode 100644 index 0000000000..56430cfb24 --- /dev/null +++ b/test/sankey-node-sorting.html @@ -0,0 +1,87 @@ + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + +