From 396236405809dd697d6f9c64093f3c4a7e1636bd Mon Sep 17 00:00:00 2001 From: Ovilia Date: Thu, 5 Sep 2024 14:49:03 +0800 Subject: [PATCH 1/3] feat(sankey): sankey support roam --- src/chart/sankey/SankeySeries.ts | 14 +++- src/chart/sankey/SankeyView.ts | 71 ++++++++++++++++ test/sankey-roam.html | 135 +++++++++++++++++++++++++++++++ 3 files changed, 218 insertions(+), 2 deletions(-) create mode 100644 test/sankey-roam.html diff --git a/src/chart/sankey/SankeySeries.ts b/src/chart/sankey/SankeySeries.ts index 9dca447cad..1826ea4e7d 100644 --- a/src/chart/sankey/SankeySeries.ts +++ b/src/chart/sankey/SankeySeries.ts @@ -34,12 +34,14 @@ import { GraphEdgeItemObject, OptionDataValueNumeric, DefaultEmphasisFocus, - CallbackDataParams + CallbackDataParams, + RoamOptionMixin } from '../../util/types'; import GlobalModel from '../../model/Global'; import SeriesData from '../../data/SeriesData'; import { LayoutRect } from '../../util/layout'; import { createTooltipMarkup } from '../../component/tooltip/tooltipMarkup'; +import View from '../../coord/View'; type FocusNodeAdjacency = boolean | 'inEdges' | 'outEdges' | 'allEdges'; @@ -95,7 +97,8 @@ export interface SankeyLevelOption extends SankeyNodeStateOption, SankeyEdgeStat export interface SankeySeriesOption extends SeriesOption, ExtraStateOption>, SankeyBothStateOption, - BoxLayoutOptionMixin { + BoxLayoutOptionMixin, + RoamOptionMixin { type?: 'sankey' /** @@ -148,6 +151,8 @@ class SankeySeriesModel extends SeriesModel { static readonly type = 'series.sankey'; readonly type = SankeySeriesModel.type; + coordinateSystem: View; + levelModels: Model[]; layoutInfo: LayoutRect; @@ -297,6 +302,11 @@ class SankeySeriesModel extends SeriesModel { layoutIterations: 32, + // true | false | 'move' | 'scale', see module:component/helper/RoamController. + roam: false, + center: null, + zoom: 1, + label: { show: true, position: 'right', diff --git a/src/chart/sankey/SankeyView.ts b/src/chart/sankey/SankeyView.ts index e84b7f7ee8..47cf89e513 100644 --- a/src/chart/sankey/SankeyView.ts +++ b/src/chart/sankey/SankeyView.ts @@ -31,6 +31,11 @@ import { setLabelStyle, getLabelStatesModels } from '../../label/labelStyle'; import { getECData } from '../../util/innerStore'; import { isString, retrieve3 } from 'zrender/src/core/util'; import type { GraphEdge } from '../../data/Graph'; +import RoamController from '../../component/helper/RoamController'; +import type { RoamControllerHost } from '../../component/helper/roamHelper'; +import { onIrrelevantElement } from '../../component/helper/cursorHelper'; +import * as roamHelper from '../../component/helper/roamHelper'; +import View from '../../coord/View'; class SankeyPathShape { x1 = 0; @@ -111,6 +116,17 @@ class SankeyView extends ChartView { private _data: SeriesData; + private _controller: RoamController; + private _controllerHost: RoamControllerHost; + + init(ecModel: GlobalModel, api: ExtensionAPI): void { + this._controller = new RoamController(api.getZr()); + + this._controllerHost = { + target: this.group + } as RoamControllerHost; + } + render(seriesModel: SankeySeriesModel, ecModel: GlobalModel, api: ExtensionAPI) { const sankeyView = this; const graph = seriesModel.getGraph(); @@ -131,6 +147,14 @@ class SankeyView extends ChartView { group.x = layoutInfo.x; group.y = layoutInfo.y; + const viewCoordSys = seriesModel.coordinateSystem = new View(); + viewCoordSys.zoomLimit = seriesModel.get('scaleLimit'); + viewCoordSys.setBoundingRect(layoutInfo.x, layoutInfo.y, width, height); + viewCoordSys.setCenter(seriesModel.get('center'), api); + viewCoordSys.setZoom(seriesModel.get('zoom')); + + this._updateController(seriesModel, ecModel, api); + // generate a bezire Curve for each edge graph.eachEdge(function (edge) { const curve = new SankeyPath(); @@ -346,6 +370,53 @@ class SankeyView extends ChartView { } dispose() { + this._controller && this._controller.dispose(); + this._controllerHost = null; + } + + private _updateController( + seriesModel: SankeySeriesModel, + ecModel: GlobalModel, + api: ExtensionAPI + ) { + const controller = this._controller; + const controllerHost = this._controllerHost; + const group = this.group; + controller.setPointerChecker(function (e, x, y) { + const rect = group.getBoundingRect(); + rect.applyTransform(group.transform); + return rect.contain(x, y) + && !onIrrelevantElement(e, api, seriesModel); + }); + + controller.enable(seriesModel.get('roam')); + controllerHost.zoomLimit = seriesModel.get('scaleLimit'); + controllerHost.zoom = seriesModel.coordinateSystem.getZoom(); + + controller + .off('pan') + .off('zoom') + .on('pan', (e) => { + roamHelper.updateViewOnPan(controllerHost, e.dx, e.dy); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'sankeyRoam', + dx: e.dx, + dy: e.dy + }); + }) + .on('zoom', (e) => { + roamHelper.updateViewOnZoom(controllerHost, e.scale, e.originX, e.originY); + api.dispatchAction({ + seriesId: seriesModel.id, + type: 'sankeyRoam', + zoom: e.scale, + originX: e.originX, + originY: e.originY + }); + // Only update label layout on zoom + api.updateLabelLayout(); + }); } } diff --git a/test/sankey-roam.html b/test/sankey-roam.html new file mode 100644 index 0000000000..ad749941f5 --- /dev/null +++ b/test/sankey-roam.html @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + From 041ae22280ecb4e8f4afd8adda9ff83f155466ca Mon Sep 17 00:00:00 2001 From: Ovilia Date: Mon, 23 Sep 2024 14:23:48 +0800 Subject: [PATCH 2/3] fix(sankey): fix a lint problem --- src/chart/sankey/SankeyView.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/chart/sankey/SankeyView.ts b/src/chart/sankey/SankeyView.ts index 47cf89e513..20ef1303c0 100644 --- a/src/chart/sankey/SankeyView.ts +++ b/src/chart/sankey/SankeyView.ts @@ -32,6 +32,7 @@ import { getECData } from '../../util/innerStore'; import { isString, retrieve3 } from 'zrender/src/core/util'; import type { GraphEdge } from '../../data/Graph'; import RoamController from '../../component/helper/RoamController'; +// eslint-disable-next-line no-duplicate-imports import type { RoamControllerHost } from '../../component/helper/roamHelper'; import { onIrrelevantElement } from '../../component/helper/cursorHelper'; import * as roamHelper from '../../component/helper/roamHelper'; From e3cad60c5479cca0138f0b3a89152f90f392140c Mon Sep 17 00:00:00 2001 From: Ovilia Date: Mon, 23 Sep 2024 14:37:40 +0800 Subject: [PATCH 3/3] fix(sankey): fix a lint problem --- src/chart/sankey/SankeyView.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/chart/sankey/SankeyView.ts b/src/chart/sankey/SankeyView.ts index 20ef1303c0..4581392826 100644 --- a/src/chart/sankey/SankeyView.ts +++ b/src/chart/sankey/SankeyView.ts @@ -33,7 +33,6 @@ import { isString, retrieve3 } from 'zrender/src/core/util'; import type { GraphEdge } from '../../data/Graph'; import RoamController from '../../component/helper/RoamController'; // eslint-disable-next-line no-duplicate-imports -import type { RoamControllerHost } from '../../component/helper/roamHelper'; import { onIrrelevantElement } from '../../component/helper/cursorHelper'; import * as roamHelper from '../../component/helper/roamHelper'; import View from '../../coord/View'; @@ -118,14 +117,14 @@ class SankeyView extends ChartView { private _data: SeriesData; private _controller: RoamController; - private _controllerHost: RoamControllerHost; + private _controllerHost: roamHelper.RoamControllerHost; init(ecModel: GlobalModel, api: ExtensionAPI): void { this._controller = new RoamController(api.getZr()); this._controllerHost = { target: this.group - } as RoamControllerHost; + } as roamHelper.RoamControllerHost; } render(seriesModel: SankeySeriesModel, ecModel: GlobalModel, api: ExtensionAPI) {