From 7c4825139617378f549ab5e01fd7cfaa137dfb5a Mon Sep 17 00:00:00 2001 From: susiwen8 Date: Sun, 3 May 2026 00:21:11 +0800 Subject: [PATCH 1/3] Keep toolbox dataZoom from dropping stacked areas Toolbox dataZoom injects select dataZoom components for both axes. When the value axis is scaled, its window is derived from the stacked coordinate extent, but filtering still used the original value dimension, so stacked area series could be filtered away before render. Reuse the axis extent dimension selection so dataZoom filters stacked series by their rendered stack result dimension. Constraint: toolbox dataZoom creates internal value-axis filters even before users actively zoom. Rejected: Force toolbox dataZoom to filterMode empty | changes existing dataZoom semantics and revives an older workaround. Confidence: high Scope-risk: narrow Directive: Keep dataZoom filtering dimensions aligned with axis extent calculation for stacked data. Tested: ./node_modules/.bin/jest --config test/ut/jest.config.cjs --coverage=false test/ut/spec/component/dataZoom --runInBand Tested: npm run checktype Tested: ./node_modules/.bin/eslint src/component/dataZoom/AxisProxy.ts test/ut/spec/component/dataZoom/AxisProxy.test.ts Tested: git diff --check -- src/component/dataZoom/AxisProxy.ts test/toolbox-dataZoom-stack-area.html test/ut/spec/component/dataZoom/AxisProxy.test.ts Tested: Chrome headless screenshot of test/toolbox-dataZoom-stack-area.html Not-tested: npm run checkheader fails on pre-existing unrelated files missing headers. --- src/component/dataZoom/AxisProxy.ts | 6 +- test/toolbox-dataZoom-stack-area.html | 137 ++++++++++++++++++ .../spec/component/dataZoom/AxisProxy.test.ts | 68 +++++++++ 3 files changed, 209 insertions(+), 2 deletions(-) create mode 100644 test/toolbox-dataZoom-stack-area.html create mode 100644 test/ut/spec/component/dataZoom/AxisProxy.test.ts diff --git a/src/component/dataZoom/AxisProxy.ts b/src/component/dataZoom/AxisProxy.ts index 11d5f6c742..f4c8138cd1 100644 --- a/src/component/dataZoom/AxisProxy.ts +++ b/src/component/dataZoom/AxisProxy.ts @@ -27,7 +27,7 @@ import { Dictionary } from '../../util/types'; // TODO Polar? import DataZoomModel from './DataZoomModel'; import { AxisBaseModel } from '../../coord/AxisBaseModel'; -import { unionAxisExtentFromData } from '../../coord/axisHelper'; +import { getDataDimensionsOnAxis, unionAxisExtentFromData } from '../../coord/axisHelper'; import { ensureScaleRawExtentInfo } from '../../coord/scaleRawExtentInfo'; import { getAxisMainType, isCoordSupported, DataZoomAxisDimension } from './helper'; import { SINGLE_REFERRING } from '../../util/model'; @@ -297,7 +297,9 @@ class AxisProxy { each(seriesModels, function (seriesModel) { let seriesData = seriesModel.getData(); - const dataDims = seriesData.mapDimensionsAll(axisDim); + // Use the same dimensions as axis extent calculation. Stacked series + // are rendered by their stack result dimension, not the original value dimension. + const dataDims = getDataDimensionsOnAxis(seriesData, axisDim); if (!dataDims.length) { return; diff --git a/test/toolbox-dataZoom-stack-area.html b/test/toolbox-dataZoom-stack-area.html new file mode 100644 index 0000000000..f7f70b30a6 --- /dev/null +++ b/test/toolbox-dataZoom-stack-area.html @@ -0,0 +1,137 @@ + + + + + + + + + + + +
+ + + diff --git a/test/ut/spec/component/dataZoom/AxisProxy.test.ts b/test/ut/spec/component/dataZoom/AxisProxy.test.ts new file mode 100644 index 0000000000..df6cf1995b --- /dev/null +++ b/test/ut/spec/component/dataZoom/AxisProxy.test.ts @@ -0,0 +1,68 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +import { createChart, getECModel } from '../../../core/utHelper'; +import { EChartsType } from '../../../../../src/echarts'; + + +describe('dataZoom/AxisProxy', function () { + + let chart: EChartsType; + beforeEach(function () { + chart = createChart(); + }); + + afterEach(function () { + chart.dispose(); + }); + + it('keeps stacked line data when toolbox dataZoom injects value-axis filtering', function () { + chart.setOption({ + toolbox: { + feature: { + dataZoom: {} + } + }, + xAxis: { + type: 'category', + boundaryGap: false, + data: ['Mon', 'Tue', 'Wed'] + }, + yAxis: { + scale: true + }, + series: [{ + type: 'line', + stack: 'total', + data: [100, 100, 100] + }, { + type: 'line', + stack: 'total', + areaStyle: {}, + data: [1, 2, 3] + }] + }); + + const data = getECModel(chart).getSeriesByIndex(1).getData(); + const stackResultDim = data.getCalculationInfo('stackResultDimension'); + expect(data.count()).toEqual(3); + expect(data.get(stackResultDim, 0)).toEqual(101); + }); + +}); From 53edc47511b5d15709ac832eb0ec9eadc7f2a23b Mon Sep 17 00:00:00 2001 From: susiwen8 Date: Sun, 3 May 2026 00:35:33 +0800 Subject: [PATCH 2/3] Cover toolbox dataZoom filter modes for stacked data Copilot noted that the AxisProxy change touches weakFilter and raised concern about empty mode. Add focused coverage for both paths so the stacked-dimension filtering contract is explicit. Constraint: toolbox dataZoom exposes filterMode and may inject value-axis filters before user zoom actions. Rejected: Revert empty mode to raw axis dimensions | tests show stackResultDimension is the rendered value and should be emptied directly. Confidence: high Scope-risk: narrow Directive: Keep weakFilter and empty coverage when changing stacked dataZoom dimensions. Tested: ./node_modules/.bin/jest --config test/ut/jest.config.cjs --coverage=false test/ut/spec/component/dataZoom --runInBand Tested: npm run checktype Tested: ./node_modules/.bin/eslint test/ut/spec/component/dataZoom/AxisProxy.test.ts Tested: git diff --check -- test/ut/spec/component/dataZoom/AxisProxy.test.ts Not-tested: npm run checkheader not rerun for this test-only follow-up; previous run failed on pre-existing unrelated files. --- .../spec/component/dataZoom/AxisProxy.test.ts | 55 ++++++++++++++++++- 1 file changed, 53 insertions(+), 2 deletions(-) diff --git a/test/ut/spec/component/dataZoom/AxisProxy.test.ts b/test/ut/spec/component/dataZoom/AxisProxy.test.ts index df6cf1995b..476a1e43c0 100644 --- a/test/ut/spec/component/dataZoom/AxisProxy.test.ts +++ b/test/ut/spec/component/dataZoom/AxisProxy.test.ts @@ -32,11 +32,13 @@ describe('dataZoom/AxisProxy', function () { chart.dispose(); }); - it('keeps stacked line data when toolbox dataZoom injects value-axis filtering', function () { + function setToolboxStackedLineOption(filterMode?: 'filter' | 'weakFilter' | 'empty') { chart.setOption({ toolbox: { feature: { - dataZoom: {} + dataZoom: filterMode + ? {filterMode: filterMode} + : {} } }, xAxis: { @@ -58,6 +60,19 @@ describe('dataZoom/AxisProxy', function () { data: [1, 2, 3] }] }); + } + + it('keeps stacked line data when toolbox dataZoom injects value-axis filtering', function () { + setToolboxStackedLineOption(); + + const data = getECModel(chart).getSeriesByIndex(1).getData(); + const stackResultDim = data.getCalculationInfo('stackResultDimension'); + expect(data.count()).toEqual(3); + expect(data.get(stackResultDim, 0)).toEqual(101); + }); + + it('keeps stacked line data when toolbox dataZoom uses weakFilter', function () { + setToolboxStackedLineOption('weakFilter'); const data = getECModel(chart).getSeriesByIndex(1).getData(); const stackResultDim = data.getCalculationInfo('stackResultDimension'); @@ -65,4 +80,40 @@ describe('dataZoom/AxisProxy', function () { expect(data.get(stackResultDim, 0)).toEqual(101); }); + it('empties stacked line data by stack result dimension', function () { + chart.setOption({ + xAxis: { + type: 'category', + boundaryGap: false, + data: ['Mon', 'Tue', 'Wed'] + }, + yAxis: { + scale: true + }, + dataZoom: { + yAxisIndex: 0, + filterMode: 'empty', + startValue: 102, + endValue: 103 + }, + series: [{ + type: 'line', + stack: 'total', + data: [100, 100, 100] + }, { + type: 'line', + stack: 'total', + areaStyle: {}, + data: [1, 2, 3] + }] + }); + + const data = getECModel(chart).getSeriesByIndex(1).getData(); + const stackResultDim = data.getCalculationInfo('stackResultDimension'); + expect(data.count()).toEqual(3); + expect(isNaN(data.get(stackResultDim, 0) as number)).toEqual(true); + expect(data.get(stackResultDim, 1)).toEqual(102); + expect(data.get(stackResultDim, 2)).toEqual(103); + }); + }); From 7d0292f58f7ac2c90036c5622fe0fc39c6ec4fdb Mon Sep 17 00:00:00 2001 From: susiwen8 Date: Sun, 3 May 2026 00:41:44 +0800 Subject: [PATCH 3/3] Assert empty dataZoom preserves in-window raw stack values Copilot suggested using raw axis dimensions for empty mode. A temporary verification showed that change turns raw y values for in-window stacked points into NaN, even though their stack result remains visible. Preserve the current implementation and cover that invariant explicitly. Constraint: mapDimensionsAll(axisDim) includes both raw value and stack result dimensions for stacked series. Rejected: Apply Copilot empty-mode suggestion | it corrupts raw values for in-window stacked points. Confidence: high Scope-risk: narrow Directive: Do not special-case empty mode to mapDimensionsAll without preserving raw stacked values. Tested: ./node_modules/.bin/jest --config test/ut/jest.config.cjs --coverage=false test/ut/spec/component/dataZoom --runInBand Tested: npm run checktype Tested: ./node_modules/.bin/eslint test/ut/spec/component/dataZoom/AxisProxy.test.ts Tested: git diff --check -- test/ut/spec/component/dataZoom/AxisProxy.test.ts --- test/ut/spec/component/dataZoom/AxisProxy.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/ut/spec/component/dataZoom/AxisProxy.test.ts b/test/ut/spec/component/dataZoom/AxisProxy.test.ts index 476a1e43c0..2c0d03ed17 100644 --- a/test/ut/spec/component/dataZoom/AxisProxy.test.ts +++ b/test/ut/spec/component/dataZoom/AxisProxy.test.ts @@ -114,6 +114,8 @@ describe('dataZoom/AxisProxy', function () { expect(isNaN(data.get(stackResultDim, 0) as number)).toEqual(true); expect(data.get(stackResultDim, 1)).toEqual(102); expect(data.get(stackResultDim, 2)).toEqual(103); + expect(data.get('y', 1)).toEqual(2); + expect(data.get('y', 2)).toEqual(3); }); });