Skip to content

Commit add0d27

Browse files
[charts] Fix infinite tick number when zoom range is zero (#17750)
1 parent 97cc309 commit add0d27

File tree

5 files changed

+48
-22
lines changed

5 files changed

+48
-22
lines changed

packages/x-charts/src/hooks/useTicks.ts

-18
Original file line numberDiff line numberDiff line change
@@ -46,24 +46,6 @@ export interface TickParams {
4646
tickLabelPlacement?: 'middle' | 'tick';
4747
}
4848

49-
export function getTickNumber(
50-
params: TickParams & {
51-
range: number[];
52-
domain: any[];
53-
},
54-
) {
55-
const { tickMaxStep, tickMinStep, tickNumber, range, domain } = params;
56-
57-
const maxTicks =
58-
tickMinStep === undefined ? 999 : Math.floor(Math.abs(domain[1] - domain[0]) / tickMinStep);
59-
const minTicks =
60-
tickMaxStep === undefined ? 2 : Math.ceil(Math.abs(domain[1] - domain[0]) / tickMaxStep);
61-
62-
const defaultizedTickNumber = tickNumber ?? Math.floor(Math.abs(range[1] - range[0]) / 50);
63-
64-
return Math.min(maxTicks, Math.max(minTicks, defaultizedTickNumber));
65-
}
66-
6749
const offsetRatio = {
6850
start: 0,
6951
extremities: 0,

packages/x-charts/src/internals/plugins/featurePlugins/useChartCartesianAxis/computeAxisValue.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
} from '../../../../models/axis';
1414
import { CartesianChartSeriesType, ChartSeriesType } from '../../../../models/seriesType/config';
1515
import { getColorScale, getOrdinalColorScale } from '../../../colorScale';
16-
import { getTickNumber } from '../../../../hooks/useTicks';
16+
import { getTickNumber, scaleTickNumberByRange } from '../../../ticks';
1717
import { getScale } from '../../../getScale';
1818
import { zoomScaleRange } from './zoom';
1919
import { getAxisExtremum } from './getAxisExtremum';
@@ -200,7 +200,7 @@ export function computeAxisValue<T extends ChartSeriesType>({
200200
}
201201

202202
const rawTickNumber = getTickNumber({ ...axis, range, domain: axisExtremums });
203-
const tickNumber = rawTickNumber / ((zoomRange[1] - zoomRange[0]) / 100);
203+
const tickNumber = scaleTickNumberByRange(rawTickNumber, zoomRange);
204204

205205
const zoomedRange = zoomScaleRange(range, zoomRange);
206206

packages/x-charts/src/internals/plugins/featurePlugins/useChartPolarAxis/computeAxisValue.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from '../../../../models/axis';
1313
import { ChartSeriesType, PolarChartSeriesType } from '../../../../models/seriesType/config';
1414
import { getColorScale, getOrdinalColorScale } from '../../../colorScale';
15-
import { getTickNumber } from '../../../../hooks/useTicks';
15+
import { getTickNumber, scaleTickNumberByRange } from '../../../ticks';
1616
import { getScale } from '../../../getScale';
1717
import { getAxisExtremum } from './getAxisExtremum';
1818
import type { ChartDrawingArea } from '../../../../hooks';
@@ -200,7 +200,7 @@ export function computeAxisValue<T extends ChartSeriesType>({
200200
}
201201

202202
const rawTickNumber = getTickNumber({ ...axis, range, domain: axisExtremums });
203-
const tickNumber = rawTickNumber / ((range[1] - range[0]) / 100);
203+
const tickNumber = scaleTickNumberByRange(rawTickNumber, range);
204204

205205
const scale = getScale(scaleType, axisExtremums, range);
206206
const finalScale = domainLimit === 'nice' ? scale.nice(rawTickNumber) : scale;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { expect } from 'chai';
2+
import { scaleTickNumberByRange } from './ticks';
3+
4+
describe('scaleTickNumberByRange', () => {
5+
it('should return 1 when rangeGap is 0 (range start and end are the same)', () => {
6+
const result = scaleTickNumberByRange(10, [50, 50]);
7+
expect(result).to.equal(1);
8+
});
9+
10+
it('should correctly scale tickNumber based on range', () => {
11+
const result = scaleTickNumberByRange(100, [0, 50]);
12+
expect(result).to.equal(200);
13+
});
14+
});
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import type { TickParams } from '../hooks/useTicks';
2+
3+
export function getTickNumber(
4+
params: TickParams & {
5+
range: number[];
6+
domain: any[];
7+
},
8+
) {
9+
const { tickMaxStep, tickMinStep, tickNumber, range, domain } = params;
10+
11+
const maxTicks =
12+
tickMinStep === undefined ? 999 : Math.floor(Math.abs(domain[1] - domain[0]) / tickMinStep);
13+
const minTicks =
14+
tickMaxStep === undefined ? 2 : Math.ceil(Math.abs(domain[1] - domain[0]) / tickMaxStep);
15+
16+
const defaultizedTickNumber = tickNumber ?? Math.floor(Math.abs(range[1] - range[0]) / 50);
17+
18+
return Math.min(maxTicks, Math.max(minTicks, defaultizedTickNumber));
19+
}
20+
21+
export function scaleTickNumberByRange(tickNumber: number, range: number[]) {
22+
const rangeGap = range[1] - range[0];
23+
24+
/* If the range start and end are the same, `tickNumber` will become infinity, so we default to 1. */
25+
if (rangeGap === 0) {
26+
return 1;
27+
}
28+
29+
return tickNumber / ((range[1] - range[0]) / 100);
30+
}

0 commit comments

Comments
 (0)