This is an automated email from the ASF dual-hosted git repository. susiwen8 pushed a commit to branch codex/fix-toolbox-stack-21111 in repository https://gitbox.apache.org/repos/asf/echarts.git
commit 7c4825139617378f549ab5e01fd7cfaa137dfb5a Author: susiwen8 <[email protected]> AuthorDate: Sun May 3 00:21:11 2026 +0800 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 ++++++++++++++++++++++ test/ut/spec/component/dataZoom/AxisProxy.test.ts | 68 +++++++++++ 3 files changed, 209 insertions(+), 2 deletions(-) diff --git a/src/component/dataZoom/AxisProxy.ts b/src/component/dataZoom/AxisProxy.ts index 11d5f6c74..f4c8138cd 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 000000000..f7f70b30a --- /dev/null +++ b/test/toolbox-dataZoom-stack-area.html @@ -0,0 +1,137 @@ +<!-- +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. +--> + +<html> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1" /> + <script src="lib/simpleRequire.js"></script> + <script src="lib/config.js"></script> + </head> + <body> + <style> + html, body { + margin: 0; + width: 100%; + height: 100%; + } + #main { + width: 100%; + height: 100%; + } + </style> + <div id="main"></div> + <script> + require(['echarts'], function (echarts) { + var lower = [0.202, 0.198, 0.194, 0.190, 0.186, 0.181, 0.178, 0.173]; + var band = [0.045, 0.043, 0.041, 0.039, 0.036, 0.035, 0.036, 0.034]; + var upper = lower.map(function (value, index) { + return +(value + band[index]).toFixed(3); + }); + var middle = lower.map(function (value, index) { + return +(value + band[index] / 2).toFixed(3); + }); + + var chart = echarts.init(document.getElementById('main')); + chart.setOption({ + animation: false, + color: ['#8ebdff', '#5b9cff', '#8ebdff'], + toolbox: { + right: 20, + feature: { + dataZoom: {} + } + }, + grid: { + left: 70, + right: 60, + top: 40, + bottom: 55 + }, + xAxis: { + type: 'category', + boundaryGap: false, + data: ['17', '04:00', '08:00', '12:00', '16:00', '20:00', '00:00', '04:00'] + }, + yAxis: { + scale: true, + splitLine: { + lineStyle: { + color: '#d8e1f2' + } + } + }, + series: [{ + name: 'lower', + type: 'line', + symbol: 'none', + data: lower, + lineStyle: { + type: 'dashed', + width: 2, + color: '#8ebdff' + } + }, { + name: 'band-base', + type: 'line', + stack: 'confidence-band', + symbol: 'none', + data: lower, + lineStyle: { + opacity: 0 + } + }, { + name: 'band', + type: 'line', + stack: 'confidence-band', + symbol: 'none', + data: band, + areaStyle: { + color: 'rgba(91, 156, 255, 0.35)' + }, + lineStyle: { + opacity: 0 + } + }, { + name: 'middle', + type: 'line', + symbol: 'none', + data: middle, + lineStyle: { + width: 2, + color: '#5b9cff' + } + }, { + name: 'upper', + type: 'line', + symbol: 'none', + data: upper, + lineStyle: { + type: 'dashed', + width: 2, + color: '#8ebdff' + } + }] + }); + window.__ECHARTS_21111_CHART__ = chart; + window.__EC_TEST_READY__ = true; + }); + </script> + </body> +</html> 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 000000000..df6cf1995 --- /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); + }); + +}); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
