This is an automated email from the ASF dual-hosted git repository. 100pah pushed a commit to branch fix/axis-min-max in repository https://gitbox.apache.org/repos/asf/echarts.git
commit 8040410319628f430a9d005b28565b8d8c5e92c6 Author: 100pah <[email protected]> AuthorDate: Sat May 30 22:33:17 2026 +0800 fix: Make axis.min/max behave consistently with series.data and axis.dataMin - illegal values are ignored. The previous behavior (before v6.1.0) is partially reasonable: `axis.min/max: NaN` coincidentally results in correct series rendering but abnormal axisLabel rendering, and cause axis extent to be series min/max. v6.1.0 introduces a breaking - `axis.min: NaN` causes axis to be blank and series not to be rendered. The current behavior is both reasonable and the closest to previous [...] --- src/coord/scaleRawExtentInfo.ts | 22 ++++-- test/axis-extreme2.html | 130 +++++++++++++++++++++++++++++++- test/lib/testHelper.js | 11 ++- test/runTest/actions/__meta__.json | 2 +- test/runTest/actions/axis-extreme2.json | 2 +- 5 files changed, 157 insertions(+), 10 deletions(-) diff --git a/src/coord/scaleRawExtentInfo.ts b/src/coord/scaleRawExtentInfo.ts index 71e2ce34a..3773ff733 100644 --- a/src/coord/scaleRawExtentInfo.ts +++ b/src/coord/scaleRawExtentInfo.ts @@ -243,15 +243,22 @@ export class ScaleRawExtentInfo { fixMM[0] = true; } else { - noZoomEffMM[0] = parseAxisModelMinMax( + const parsedMin = parseAxisModelMinMax( scale, isFunction(modelMinRaw) // This callback always provides users the full data extent (before data is filtered). ? modelMinRaw({min: dataMM[0], max: dataMM[1]}) : modelMinRaw ); - // If `xxxAxis.min: null/undefined`, min should not be fixed. - fixMM[0] = noZoomEffMM[0] != null; + if (isValidNumberForExtent(parsedMin)) { + // Follow the treatment of seriesData and axis.dataMin - illegal values are ignored. + // MEMO: The previous behavior (before v6.1.0) is partially reasonable: `axis.min: NaN` + // coincidentally results in correct series rendering but abnormal axisLabel rendering, + // and cause `fixMM[0] = true`. The current behavior is both reasonable and the closest + // to previous behavior. + fixMM[0] = true; + noZoomEffMM[0] = parsedMin; + } } const modelMaxRaw = model.get('max', true); @@ -260,15 +267,18 @@ export class ScaleRawExtentInfo { fixMM[1] = true; } else { - noZoomEffMM[1] = parseAxisModelMinMax( + const parsedMax = parseAxisModelMinMax( scale, isFunction(modelMaxRaw) // This callback always provides users the full data extent (before data is filtered). ? modelMaxRaw({min: dataMM[0], max: dataMM[1]}) : modelMaxRaw ); - // If `xxxAxis.max: null/undefined`, max should not be fixed. - fixMM[1] = noZoomEffMM[1] != null; + if (isValidNumberForExtent(parsedMax)) { + // Follow the treatment of seriesData and axis.dataMin - illegal values are ignored. + fixMM[1] = true; + noZoomEffMM[1] = parsedMax; + } } const boundaryGap = parseBoundaryGapOption(scale, model); diff --git a/test/axis-extreme2.html b/test/axis-extreme2.html index cb50cc0e9..5da1625d5 100644 --- a/test/axis-extreme2.html +++ b/test/axis-extreme2.html @@ -43,7 +43,7 @@ under the License. <div id="main0"></div> - + <div id="main1"></div> @@ -154,6 +154,134 @@ under the License. </script> + + + + + <script> + + require([ + 'echarts', + ], function (echarts /*, data */) { + var seriesDataList = [ + [['a', 231], ['b', 319], ['c', NaN]], + [['a', 231], ['b', 319], ['c', NaN], ['d', Infinity], ['e', -Infinity]], + ]; + + var _ctx = { + seriesData: { + value: seriesDataList[0], + values: seriesDataList + }, + br0: {}, + yAxisMin: { + value: NaN, + values: ['NOT_SET', NaN, 93, undefined, 'dataMin', '', '-', -Infinity, -Number.MAX_SAFE_INTEGER] + }, + yAxisMax: { + value: NaN, + values: ['NOT_SET', NaN, 523, undefined, 'dataMax', '', '-', Infinity, Number.MAX_SAFE_INTEGER] + }, + yAxisScale: { + value: 'NOT_SET', + values: ['NOT_SET', true, false] + }, + br1: {}, + yAxisDataMin: { + value: 'NOT_SET', + values: ['NOT_SET', NaN, 53, undefined, '', '-', Infinity, -Number.MAX_SAFE_INTEGER] + }, + yAxisDataMax: { + value: 'NOT_SET', + values: ['NOT_SET', NaN, 723, undefined, '', '-', Infinity, Number.MAX_SAFE_INTEGER] + }, + }; + + function createOption() { + + var option = { + tooltip: { + trigger: 'axis', + axisPointer: {type: 'shadow'}, + }, + legend: {}, + xAxis: { + type: 'category', + axisLine: { + show: true, + }, + axisTick: { + show: true + }, + axisLabel: { + show: true + }, + }, + yAxis: { + axisLine: { + show: true, + }, + axisTick: { + show: true, + }, + axisLabel: { + show: true, + } + }, + series: [{ + type: 'scatter', + symbolSize: 20, + label: { + show: true, + position: 'top', + }, + }] + }; + + if (_ctx.seriesData.value !== 'NOT_SET') { + option.series[0].data = _ctx.seriesData.value; + } + if (_ctx.yAxisScale.value !== 'NOT_SET') { + option.yAxis.scale = _ctx.yAxisScale.value; + } + if (_ctx.yAxisMin.value !== 'NOT_SET') { + option.yAxis.min = _ctx.yAxisMin.value; + } + if (_ctx.yAxisMax.value !== 'NOT_SET') { + option.yAxis.max = _ctx.yAxisMax.value; + } + if (_ctx.yAxisDataMin.value !== 'NOT_SET') { + option.yAxis.dataMin = _ctx.yAxisDataMin.value; + } + if (_ctx.yAxisDataMax.value !== 'NOT_SET') { + option.yAxis.dataMax = _ctx.yAxisDataMax.value; + } + + return option; + } + + function updateChart() { + chart.setOption(createOption(), {notMerge: true}); + } + + var chart = testHelper.create(echarts, 'main1', { + title: [ + 'yAxis min/max illegal value test.', + ], + option: createOption(), + height: 300, + inputsStyle: 'compact', + inputs: testHelper.createInputsSimply(_ctx, updateChart) + + }); // End of `testHelper.create` + + }); // End of `require` + + </script> + + + + </body> </html> diff --git a/test/lib/testHelper.js b/test/lib/testHelper.js index 43d531558..7652e7c64 100644 --- a/test/lib/testHelper.js +++ b/test/lib/testHelper.js @@ -1333,7 +1333,12 @@ var found = false; for (var idx = 0; idx < selectCtx._optionList.length; idx++) { if (!selectCtx._optionList[idx].input - && selectCtx._optionList[idx].value === inputDefine.value + && ( + selectCtx._optionList[idx].value === inputDefine.value + || ( + eqNaN(selectCtx._optionList[idx].value) && eqNaN(inputDefine.value) + ) + ) ) { found = true; initOptionIdx = idx; @@ -2500,6 +2505,10 @@ : null; }; + function eqNaN(value) { + return value !== value; + } + function containsDOMElement(parent, child, includeSelf) { if (!includeSelf && child) { child = child.parentNode; diff --git a/test/runTest/actions/__meta__.json b/test/runTest/actions/__meta__.json index c0dc3b70d..c2f37f076 100644 --- a/test/runTest/actions/__meta__.json +++ b/test/runTest/actions/__meta__.json @@ -19,7 +19,7 @@ "axis-break-4": 5, "axis-data-min-max": 1, "axis-dataset-null": 1, - "axis-extreme2": 1, + "axis-extreme2": 2, "axis-filter-extent2": 1, "axis-interval": 3, "axis-interval2": 5, diff --git a/test/runTest/actions/axis-extreme2.json b/test/runTest/actions/axis-extreme2.json index 1da182d9c..997ef6744 100644 --- a/test/runTest/actions/axis-extreme2.json +++ b/test/runTest/actions/axis-extreme2.json @@ -1 +1 @@ -[{"name":"Action 2","ops":[{"type":"mousemove","time":1280,"x":596,"y":459},{"type":"mousemove","time":1481,"x":470,"y":448},{"type":"mousemove","time":1693,"x":406,"y":411},{"type":"mousemove","time":1899,"x":393,"y":393},{"type":"mousedown","time":2007,"x":390,"y":391},{"type":"mousemove","time":2106,"x":390,"y":391},{"type":"mouseup","time":2290,"x":390,"y":391},{"time":2291,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":2608,"x":390,"y":391},{"type":"mouseup","time" [...] \ No newline at end of file +[{"name":"Action 2","ops":[{"type":"mousemove","time":1280,"x":596,"y":459},{"type":"mousemove","time":1481,"x":470,"y":448},{"type":"mousemove","time":1693,"x":406,"y":411},{"type":"mousemove","time":1899,"x":393,"y":393},{"type":"mousedown","time":2007,"x":390,"y":391},{"type":"mousemove","time":2106,"x":390,"y":391},{"type":"mouseup","time":2290,"x":390,"y":391},{"time":2291,"delay":400,"type":"screenshot-auto"},{"type":"mousedown","time":2608,"x":390,"y":391},{"type":"mouseup","time" [...] \ No newline at end of file --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
