From 2a234b39612a3094b12e9931e33054926313a198 Mon Sep 17 00:00:00 2001 From: Justin-ZS Date: Mon, 10 Mar 2025 18:46:45 +0800 Subject: [PATCH 1/6] feat(visualMap): able to set the 'dimension' to an array --- src/component/visualMap/ContinuousModel.ts | 2 +- src/component/visualMap/ContinuousView.ts | 3 +- src/component/visualMap/PiecewiseModel.ts | 12 +- src/component/visualMap/VisualMapModel.ts | 13 +- src/component/visualMap/visualEncoding.ts | 4 +- test/runTest/actions/__meta__.json | 1 + test/runTest/actions/visualmap-dimension.json | 1 + test/visualmap-dimension.html | 159 ++++++++++++++++++ 8 files changed, 184 insertions(+), 11 deletions(-) create mode 100644 test/runTest/actions/visualmap-dimension.json create mode 100644 test/visualmap-dimension.html diff --git a/src/component/visualMap/ContinuousModel.ts b/src/component/visualMap/ContinuousModel.ts index 35e14aa371..21727b2c3c 100644 --- a/src/component/visualMap/ContinuousModel.ts +++ b/src/component/visualMap/ContinuousModel.ts @@ -221,7 +221,7 @@ class ContinuousModel extends VisualMapModel { const dataIndices: number[] = []; const data = seriesModel.getData(); - data.each(this.getDataDimensionIndex(data), function (value: number, dataIndex) { + data.each(this.getDataDimensionIndex(data, seriesModel.seriesIndex), function (value: number, dataIndex) { range[0] <= value && value <= range[1] && dataIndices.push(dataIndex); }, this); diff --git a/src/component/visualMap/ContinuousView.ts b/src/component/visualMap/ContinuousView.ts index 6d8710cf1c..d37a22ffdc 100644 --- a/src/component/visualMap/ContinuousView.ts +++ b/src/component/visualMap/ContinuousView.ts @@ -855,7 +855,8 @@ class ContinuousView extends VisualMapView { } const data = dataModel.getData(ecData.dataType); - const value = data.getStore().get(visualMapModel.getDataDimensionIndex(data), ecData.dataIndex) as number; + const value = data.getStore() + .get(visualMapModel.getDataDimensionIndex(data, dataModel.seriesIndex), ecData.dataIndex) as number; if (!isNaN(value)) { this._showIndicator(value, value); diff --git a/src/component/visualMap/PiecewiseModel.ts b/src/component/visualMap/PiecewiseModel.ts index ef5913a62a..b16792d9bf 100644 --- a/src/component/visualMap/PiecewiseModel.ts +++ b/src/component/visualMap/PiecewiseModel.ts @@ -313,11 +313,13 @@ class PiecewiseModel extends VisualMapModel { const dataIndices: number[] = []; const data = seriesModel.getData(); - data.each(this.getDataDimensionIndex(data), function (value: number, dataIndex: number) { - // Should always base on model pieceList, because it is order sensitive. - const pIdx = VisualMapping.findPieceIndex(value, pieceList); - pIdx === pieceIndex && dataIndices.push(dataIndex); - }, this); + data.each( + this.getDataDimensionIndex(data, seriesModel.seriesIndex), + function (value: number, dataIndex: number) { + // Should always base on model pieceList, because it is order sensitive. + const pIdx = VisualMapping.findPieceIndex(value, pieceList); + pIdx === pieceIndex && dataIndices.push(dataIndex); + }, this); result.push({seriesId: seriesModel.id, dataIndex: dataIndices}); }, this); diff --git a/src/component/visualMap/VisualMapModel.ts b/src/component/visualMap/VisualMapModel.ts index d2756a4a99..7a045d43fc 100644 --- a/src/component/visualMap/VisualMapModel.ts +++ b/src/component/visualMap/VisualMapModel.ts @@ -91,7 +91,7 @@ export interface VisualMapOption /** * Dimension to be encoded */ - dimension?: number + dimension?: number | number[] /** * Visual configuration for the data in selection @@ -406,8 +406,17 @@ class VisualMapModel extends Com // } // } - getDataDimensionIndex(data: SeriesData): DimensionIndex { + getDimension(seriesIndex: number): number { const optDim = this.option.dimension; + if (isArray(optDim) && seriesIndex != null) { + const idx = this.getTargetSeriesIndices().indexOf(seriesIndex); + return optDim[idx] ?? optDim[optDim.length - 1]; + } + return [].concat(optDim)[0]; + } + + getDataDimensionIndex(data: SeriesData, seriesIndex: number): DimensionIndex { + const optDim = this.getDimension(seriesIndex); if (optDim != null) { return data.getDimensionIndex(optDim); diff --git a/src/component/visualMap/visualEncoding.ts b/src/component/visualMap/visualEncoding.ts index 6f090b3694..4a6e4dcbde 100644 --- a/src/component/visualMap/visualEncoding.ts +++ b/src/component/visualMap/visualEncoding.ts @@ -42,7 +42,7 @@ export const visualMapEncodingHandlers: StageHandler[] = [ visualMapModel.stateList, visualMapModel.targetVisuals, zrUtil.bind(visualMapModel.getValueState, visualMapModel), - visualMapModel.getDataDimensionIndex(seriesModel.getData()) + visualMapModel.getDataDimensionIndex(seriesModel.getData(), seriesModel.seriesIndex) )); }); @@ -65,7 +65,7 @@ export const visualMapEncodingHandlers: StageHandler[] = [ outerColors: [] } as VisualMeta; - const dimIdx = visualMapModel.getDataDimensionIndex(data); + const dimIdx = visualMapModel.getDataDimensionIndex(data, seriesModel.seriesIndex); if (dimIdx >= 0) { // visualMeta.dimension should be dimension index, but not concrete dimension. visualMeta.dimension = dimIdx; diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json index 10f3d0937f..ab120d737c 100644 --- a/test/runTest/actions/__meta__.json +++ b/test/runTest/actions/__meta__.json @@ -238,6 +238,7 @@ "universalTransition2": 3, "universalTransition3": 2, "visualMap-categories": 1, + "visualmap-dimension": 3, "visualMap-multi-continuous": 1, "visualMap-on-data": 1, "visualMap-selectMode": 2 diff --git a/test/runTest/actions/visualmap-dimension.json b/test/runTest/actions/visualmap-dimension.json new file mode 100644 index 0000000000..76f661676b --- /dev/null +++ b/test/runTest/actions/visualmap-dimension.json @@ -0,0 +1 @@ +[{"name":"Action 1","ops":[{"type":"screenshot","time":1195}],"scrollY":0,"scrollX":0,"timestamp":1737368248568},{"name":"Action 2","ops":[{"type":"screenshot","time":532}],"scrollY":678,"scrollX":0,"timestamp":1737368258531},{"name":"Action 3","ops":[{"type":"screenshot","time":357}],"scrollY":1334,"scrollX":0,"timestamp":1737368264539}] \ No newline at end of file diff --git a/test/visualmap-dimension.html b/test/visualmap-dimension.html new file mode 100644 index 0000000000..6ecbf77840 --- /dev/null +++ b/test/visualmap-dimension.html @@ -0,0 +1,159 @@ + + + + + + + + + + + + + + + + + + + + + + + + From a762c7bc2118ec0de7c11ba9c02b540d4a4dae27 Mon Sep 17 00:00:00 2001 From: Justin-ZS Date: Mon, 29 Sep 2025 09:30:49 +0800 Subject: [PATCH 2/6] feat(visualMap): add seriesTargets to mapping different series -> dimension --- src/component/visualMap/ContinuousModel.ts | 2 +- src/component/visualMap/ContinuousView.ts | 2 +- src/component/visualMap/PiecewiseModel.ts | 2 +- src/component/visualMap/VisualMapModel.ts | 58 ++++++- src/component/visualMap/preprocessor.ts | 17 ++ src/component/visualMap/visualEncoding.ts | 4 +- test/runTest/actions/__meta__.json | 1 - test/runTest/actions/visualmap-dimension.json | 1 - test/visualmap-dimension.html | 159 ------------------ test/visualmap-seriesTargets.html | 77 +++++++++ 10 files changed, 148 insertions(+), 175 deletions(-) delete mode 100644 test/runTest/actions/visualmap-dimension.json delete mode 100644 test/visualmap-dimension.html create mode 100644 test/visualmap-seriesTargets.html diff --git a/src/component/visualMap/ContinuousModel.ts b/src/component/visualMap/ContinuousModel.ts index 21727b2c3c..35e14aa371 100644 --- a/src/component/visualMap/ContinuousModel.ts +++ b/src/component/visualMap/ContinuousModel.ts @@ -221,7 +221,7 @@ class ContinuousModel extends VisualMapModel { const dataIndices: number[] = []; const data = seriesModel.getData(); - data.each(this.getDataDimensionIndex(data, seriesModel.seriesIndex), function (value: number, dataIndex) { + data.each(this.getDataDimensionIndex(data), function (value: number, dataIndex) { range[0] <= value && value <= range[1] && dataIndices.push(dataIndex); }, this); diff --git a/src/component/visualMap/ContinuousView.ts b/src/component/visualMap/ContinuousView.ts index d37a22ffdc..ee60c9de2b 100644 --- a/src/component/visualMap/ContinuousView.ts +++ b/src/component/visualMap/ContinuousView.ts @@ -856,7 +856,7 @@ class ContinuousView extends VisualMapView { const data = dataModel.getData(ecData.dataType); const value = data.getStore() - .get(visualMapModel.getDataDimensionIndex(data, dataModel.seriesIndex), ecData.dataIndex) as number; + .get(visualMapModel.getDataDimensionIndex(data), ecData.dataIndex) as number; if (!isNaN(value)) { this._showIndicator(value, value); diff --git a/src/component/visualMap/PiecewiseModel.ts b/src/component/visualMap/PiecewiseModel.ts index b16792d9bf..1cf078e2a9 100644 --- a/src/component/visualMap/PiecewiseModel.ts +++ b/src/component/visualMap/PiecewiseModel.ts @@ -314,7 +314,7 @@ class PiecewiseModel extends VisualMapModel { const data = seriesModel.getData(); data.each( - this.getDataDimensionIndex(data, seriesModel.seriesIndex), + this.getDataDimensionIndex(data), function (value: number, dataIndex: number) { // Should always base on model pieceList, because it is order sensitive. const pIdx = VisualMapping.findPieceIndex(value, pieceList); diff --git a/src/component/visualMap/VisualMapModel.ts b/src/component/visualMap/VisualMapModel.ts index 7a045d43fc..f6237417a9 100644 --- a/src/component/visualMap/VisualMapModel.ts +++ b/src/component/visualMap/VisualMapModel.ts @@ -33,9 +33,9 @@ import { OptionDataValue, BuiltinVisualProperty, DimensionIndex, - OptionId, ComponentOnCalendarOptionMixin, - ComponentOnMatrixOptionMixin + ComponentOnMatrixOptionMixin, + OptionId, } from '../../util/types'; import ComponentModel from '../../model/Component'; import Model from '../../model/Model'; @@ -91,7 +91,17 @@ export interface VisualMapOption /** * Dimension to be encoded */ - dimension?: number | number[] + dimension?: number + + /** + * Series targets with specific dimensions + * When provided, seriesIndex, seriesId, and dimension are ignored + */ + seriesTargets?: { + seriesIndex?: number + seriesId?: OptionId + dimension: number + }[] /** * Visual configuration for the data in selection @@ -247,6 +257,30 @@ class VisualMapModel extends Com * @return An array of series indices. */ protected getTargetSeriesIndices(): number[] { + const seriesTargets = this.option.seriesTargets; + if (seriesTargets) { + // When seriesTargets is provided, collect all target series indices + const indices: number[] = []; + for (const target of seriesTargets) { + if (target.seriesIndex != null) { + indices.push(target.seriesIndex); + } + else if (target.seriesId != null) { + // Find series by ID + let seriesModel: SeriesModel; + this.ecModel.eachSeries(function (series) { + if (series.id === target.seriesId) { + seriesModel = series; + } + }); + if (seriesModel) { + indices.push(seriesModel.componentIndex); + } + } + } + return indices; + } + const optionSeriesId = this.option.seriesId; let optionSeriesIndex = this.option.seriesIndex; if (optionSeriesIndex == null && optionSeriesId == null) { @@ -407,15 +441,21 @@ class VisualMapModel extends Com // } getDimension(seriesIndex: number): number { - const optDim = this.option.dimension; - if (isArray(optDim) && seriesIndex != null) { - const idx = this.getTargetSeriesIndices().indexOf(seriesIndex); - return optDim[idx] ?? optDim[optDim.length - 1]; + const seriesTargets = this.option.seriesTargets; + if (seriesTargets) { + const target = seriesTargets.find(target => + (target.seriesIndex != null && target.seriesIndex === seriesIndex) + || (target.seriesId != null && target.seriesId === this.ecModel.getSeriesByIndex(seriesIndex).id) + ); + if (target) { + return target.dimension; + } } - return [].concat(optDim)[0]; + return this.option.dimension; } - getDataDimensionIndex(data: SeriesData, seriesIndex: number): DimensionIndex { + getDataDimensionIndex(data: SeriesData): DimensionIndex { + const seriesIndex = (data.hostModel as any).seriesIndex; const optDim = this.getDimension(seriesIndex); if (optDim != null) { diff --git a/src/component/visualMap/preprocessor.ts b/src/component/visualMap/preprocessor.ts index 08ba687c1d..8696680ba1 100644 --- a/src/component/visualMap/preprocessor.ts +++ b/src/component/visualMap/preprocessor.ts @@ -53,6 +53,23 @@ export default function visualMapPreprocessor(option) { } }); } + + // Validate seriesTargets + const seriesTargets = opt.seriesTargets; + if (seriesTargets && zrUtil.isArray(seriesTargets)) { + each(seriesTargets, function (target) { + if (!zrUtil.isObject(target) || target.dimension == null) { + if (__DEV__) { + console.warn('Each seriesTarget should have a dimension property'); + } + } + if (target.seriesIndex == null && target.seriesId == null) { + if (__DEV__) { + console.warn('Each seriesTarget should have either seriesIndex or seriesId'); + } + } + }); + } }); } diff --git a/src/component/visualMap/visualEncoding.ts b/src/component/visualMap/visualEncoding.ts index 4a6e4dcbde..6f090b3694 100644 --- a/src/component/visualMap/visualEncoding.ts +++ b/src/component/visualMap/visualEncoding.ts @@ -42,7 +42,7 @@ export const visualMapEncodingHandlers: StageHandler[] = [ visualMapModel.stateList, visualMapModel.targetVisuals, zrUtil.bind(visualMapModel.getValueState, visualMapModel), - visualMapModel.getDataDimensionIndex(seriesModel.getData(), seriesModel.seriesIndex) + visualMapModel.getDataDimensionIndex(seriesModel.getData()) )); }); @@ -65,7 +65,7 @@ export const visualMapEncodingHandlers: StageHandler[] = [ outerColors: [] } as VisualMeta; - const dimIdx = visualMapModel.getDataDimensionIndex(data, seriesModel.seriesIndex); + const dimIdx = visualMapModel.getDataDimensionIndex(data); if (dimIdx >= 0) { // visualMeta.dimension should be dimension index, but not concrete dimension. visualMeta.dimension = dimIdx; diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json index ab120d737c..10f3d0937f 100644 --- a/test/runTest/actions/__meta__.json +++ b/test/runTest/actions/__meta__.json @@ -238,7 +238,6 @@ "universalTransition2": 3, "universalTransition3": 2, "visualMap-categories": 1, - "visualmap-dimension": 3, "visualMap-multi-continuous": 1, "visualMap-on-data": 1, "visualMap-selectMode": 2 diff --git a/test/runTest/actions/visualmap-dimension.json b/test/runTest/actions/visualmap-dimension.json deleted file mode 100644 index 76f661676b..0000000000 --- a/test/runTest/actions/visualmap-dimension.json +++ /dev/null @@ -1 +0,0 @@ -[{"name":"Action 1","ops":[{"type":"screenshot","time":1195}],"scrollY":0,"scrollX":0,"timestamp":1737368248568},{"name":"Action 2","ops":[{"type":"screenshot","time":532}],"scrollY":678,"scrollX":0,"timestamp":1737368258531},{"name":"Action 3","ops":[{"type":"screenshot","time":357}],"scrollY":1334,"scrollX":0,"timestamp":1737368264539}] \ No newline at end of file diff --git a/test/visualmap-dimension.html b/test/visualmap-dimension.html deleted file mode 100644 index 6ecbf77840..0000000000 --- a/test/visualmap-dimension.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/test/visualmap-seriesTargets.html b/test/visualmap-seriesTargets.html new file mode 100644 index 0000000000..58d1407935 --- /dev/null +++ b/test/visualmap-seriesTargets.html @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + From 6eddf4bcc730e281fc8e14212267bdeed8c10774 Mon Sep 17 00:00:00 2001 From: Justin-ZS Date: Mon, 29 Sep 2025 09:50:56 +0800 Subject: [PATCH 3/6] test(visualmap): add more test --- test/visualmap-seriesTargets.html | 32 +++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/visualmap-seriesTargets.html b/test/visualmap-seriesTargets.html index 58d1407935..b2f483ee4e 100644 --- a/test/visualmap-seriesTargets.html +++ b/test/visualmap-seriesTargets.html @@ -71,6 +71,38 @@ } }); }); + + createCase('seriesTargets: using seriesId to target specific series', 1, function (chart) { + chart.setOption({ + tooltip: {}, + dataset: { + source: [ + ['product', 'sales', 'profit', 'growth'], + ['Product A', 120, 45, 12], + ['Product B', 200, 80, 25], + ['Product C', 150, 60, 18], + ['Product D', 80, 30, 8] + ] + }, + xAxis: { type: 'category' }, + yAxis: {}, + series: [ + { type: 'bar', id: 'sales-bar', name: 'Sales' }, + { type: 'bar', id: 'profit-bar', name: 'Profit' }, + { type: 'bar', id: 'growth-bar', name: 'Growth' } + ], + visualMap: { + type: 'continuous', + min: 0, + max: 200, + seriesTargets: [ + { seriesId: 'sales-bar', dimension: 1 }, + { seriesId: 'profit-bar', dimension: 2 }, + { seriesId: 'growth-bar', dimension: 3 } + ] + } + }); + }); }); From f6f7bdfd5db59ba4363a3bb262e473b709f257b5 Mon Sep 17 00:00:00 2001 From: Justin-ZS Date: Fri, 24 Oct 2025 18:14:06 +0800 Subject: [PATCH 4/6] fix: revert irrelevant changes --- src/component/visualMap/ContinuousView.ts | 3 +-- src/component/visualMap/PiecewiseModel.ts | 12 +++++------- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/component/visualMap/ContinuousView.ts b/src/component/visualMap/ContinuousView.ts index ee60c9de2b..6d8710cf1c 100644 --- a/src/component/visualMap/ContinuousView.ts +++ b/src/component/visualMap/ContinuousView.ts @@ -855,8 +855,7 @@ class ContinuousView extends VisualMapView { } const data = dataModel.getData(ecData.dataType); - const value = data.getStore() - .get(visualMapModel.getDataDimensionIndex(data), ecData.dataIndex) as number; + const value = data.getStore().get(visualMapModel.getDataDimensionIndex(data), ecData.dataIndex) as number; if (!isNaN(value)) { this._showIndicator(value, value); diff --git a/src/component/visualMap/PiecewiseModel.ts b/src/component/visualMap/PiecewiseModel.ts index 1cf078e2a9..ef5913a62a 100644 --- a/src/component/visualMap/PiecewiseModel.ts +++ b/src/component/visualMap/PiecewiseModel.ts @@ -313,13 +313,11 @@ class PiecewiseModel extends VisualMapModel { const dataIndices: number[] = []; const data = seriesModel.getData(); - data.each( - this.getDataDimensionIndex(data), - function (value: number, dataIndex: number) { - // Should always base on model pieceList, because it is order sensitive. - const pIdx = VisualMapping.findPieceIndex(value, pieceList); - pIdx === pieceIndex && dataIndices.push(dataIndex); - }, this); + data.each(this.getDataDimensionIndex(data), function (value: number, dataIndex: number) { + // Should always base on model pieceList, because it is order sensitive. + const pIdx = VisualMapping.findPieceIndex(value, pieceList); + pIdx === pieceIndex && dataIndices.push(dataIndex); + }, this); result.push({seriesId: seriesModel.id, dataIndex: dataIndices}); }, this); From 18c17b73ba72f219e2123c7e21ec097e0c50d50d Mon Sep 17 00:00:00 2001 From: Justin-ZS Date: Fri, 31 Oct 2025 18:09:05 +0800 Subject: [PATCH 5/6] fix: code review --- src/component/visualMap/VisualMapModel.ts | 4 ++-- src/component/visualMap/preprocessor.ts | 18 ++++++++---------- 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/component/visualMap/VisualMapModel.ts b/src/component/visualMap/VisualMapModel.ts index f6237417a9..32c1df4f9f 100644 --- a/src/component/visualMap/VisualMapModel.ts +++ b/src/component/visualMap/VisualMapModel.ts @@ -261,7 +261,7 @@ class VisualMapModel extends Com if (seriesTargets) { // When seriesTargets is provided, collect all target series indices const indices: number[] = []; - for (const target of seriesTargets) { + each(seriesTargets, (target) => { if (target.seriesIndex != null) { indices.push(target.seriesIndex); } @@ -277,7 +277,7 @@ class VisualMapModel extends Com indices.push(seriesModel.componentIndex); } } - } + }); return indices; } diff --git a/src/component/visualMap/preprocessor.ts b/src/component/visualMap/preprocessor.ts index 8696680ba1..6e86e06970 100644 --- a/src/component/visualMap/preprocessor.ts +++ b/src/component/visualMap/preprocessor.ts @@ -55,20 +55,18 @@ export default function visualMapPreprocessor(option) { } // Validate seriesTargets - const seriesTargets = opt.seriesTargets; - if (seriesTargets && zrUtil.isArray(seriesTargets)) { - each(seriesTargets, function (target) { - if (!zrUtil.isObject(target) || target.dimension == null) { - if (__DEV__) { + if (__DEV__) { + const seriesTargets = opt.seriesTargets; + if (seriesTargets && zrUtil.isArray(seriesTargets)) { + each(seriesTargets, function (target) { + if (!zrUtil.isObject(target) || target.dimension == null) { console.warn('Each seriesTarget should have a dimension property'); } - } - if (target.seriesIndex == null && target.seriesId == null) { - if (__DEV__) { + if (target.seriesIndex == null && target.seriesId == null) { console.warn('Each seriesTarget should have either seriesIndex or seriesId'); } - } - }); + }); + } } }); } From b322f2c906e1b1836bd3796b721fb5474b34b933 Mon Sep 17 00:00:00 2001 From: plainheart Date: Fri, 31 Oct 2025 18:57:28 +0800 Subject: [PATCH 6/6] style: use zrUtil.find rather than array.find --- src/component/visualMap/VisualMapModel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/component/visualMap/VisualMapModel.ts b/src/component/visualMap/VisualMapModel.ts index 32c1df4f9f..843387a465 100644 --- a/src/component/visualMap/VisualMapModel.ts +++ b/src/component/visualMap/VisualMapModel.ts @@ -443,7 +443,7 @@ class VisualMapModel extends Com getDimension(seriesIndex: number): number { const seriesTargets = this.option.seriesTargets; if (seriesTargets) { - const target = seriesTargets.find(target => + const target = zrUtil.find(seriesTargets, target => (target.seriesIndex != null && target.seriesIndex === seriesIndex) || (target.seriesId != null && target.seriesId === this.ecModel.getSeriesByIndex(seriesIndex).id) );