@@ -32,9 +32,8 @@ const useUtilityClasses = (ownerState: AxisConfig<any, any, ChartsXAxisProps>) =
32
32
return composeClasses ( slots , getAxisUtilityClass , classes ) ;
33
33
} ;
34
34
35
- type LabelExtraData = { skipLabel ?: boolean } ;
36
-
37
- function addLabelDimension (
35
+ /* Returns a set of indices of the tick labels that should be visible. */
36
+ function getVisibleLabels (
38
37
xTicks : TickItemType [ ] ,
39
38
{
40
39
tickLabelStyle : style ,
@@ -49,7 +48,7 @@ function addLabelDimension(
49
48
tickLabelMinGap : NonNullable < ChartsXAxisProps [ 'tickLabelMinGap' ] > ;
50
49
isPointInside : ( position : number ) => boolean ;
51
50
} ,
52
- ) : ( TickItemType & LabelExtraData ) [ ] {
51
+ ) : Set < TickItemType > {
53
52
const getTickLabelSize = ( tick : TickItemType ) => {
54
53
if ( ! isMounted || tick . formattedValue === undefined ) {
55
54
return { width : 0 , height : 0 } ;
@@ -64,54 +63,48 @@ function addLabelDimension(
64
63
} ;
65
64
66
65
if ( typeof tickLabelInterval === 'function' ) {
67
- return xTicks . map ( ( item , index ) => {
68
- const skipLabel = ! tickLabelInterval ( item . value , index ) ;
69
- const size = skipLabel ? { width : 0 , height : 0 } : getTickLabelSize ( item ) ;
70
-
71
- return {
72
- ...item ,
73
- ...size ,
74
- skipLabel,
75
- } ;
76
- } ) ;
66
+ return new Set ( xTicks . filter ( ( item , index ) => tickLabelInterval ( item . value , index ) ) ) ;
77
67
}
78
68
79
69
// Filter label to avoid overlap
80
70
let previousTextLimit = 0 ;
81
71
const direction = reverse ? - 1 : 1 ;
82
72
83
- return xTicks . map ( ( item , labelIndex ) => {
84
- const { offset, labelOffset } = item ;
85
- const textPosition = offset + labelOffset ;
86
-
87
- if (
88
- labelIndex > 0 &&
89
- direction * textPosition < direction * ( previousTextLimit + tickLabelMinGap )
90
- ) {
91
- return { ...item , skipLabel : true } ;
92
- }
93
-
94
- if ( ! isPointInside ( textPosition ) ) {
95
- return { ...item , skipLabel : true } ;
96
- }
97
-
98
- const { width, height } = getTickLabelSize ( item ) ;
99
-
100
- const distance = getMinXTranslation ( width , height , style ?. angle ) ;
101
-
102
- const currentTextLimit = textPosition - ( direction * distance ) / 2 ;
103
- if (
104
- labelIndex > 0 &&
105
- direction * currentTextLimit < direction * ( previousTextLimit + tickLabelMinGap )
106
- ) {
107
- // Except for the first label, we skip all label that overlap with the last accepted.
108
- // Notice that the early return prevents `previousTextLimit` from being updated.
109
- return { ...item , skipLabel : true } ;
110
- }
111
-
112
- previousTextLimit = textPosition + ( direction * distance ) / 2 ;
113
- return item ;
114
- } ) ;
73
+ return new Set (
74
+ xTicks . filter ( ( item , labelIndex ) => {
75
+ const { offset, labelOffset } = item ;
76
+ const textPosition = offset + labelOffset ;
77
+
78
+ if (
79
+ labelIndex > 0 &&
80
+ direction * textPosition < direction * ( previousTextLimit + tickLabelMinGap )
81
+ ) {
82
+ return false ;
83
+ }
84
+
85
+ if ( ! isPointInside ( textPosition ) ) {
86
+ return false ;
87
+ }
88
+
89
+ /* Measuring text width is expensive, so we need to delay it as much as possible to improve performance. */
90
+ const { width, height } = getTickLabelSize ( item ) ;
91
+
92
+ const distance = getMinXTranslation ( width , height , style ?. angle ) ;
93
+
94
+ const currentTextLimit = textPosition - ( direction * distance ) / 2 ;
95
+ if (
96
+ labelIndex > 0 &&
97
+ direction * currentTextLimit < direction * ( previousTextLimit + tickLabelMinGap )
98
+ ) {
99
+ // Except for the first label, we skip all label that overlap with the last accepted.
100
+ // Notice that the early return prevents `previousTextLimit` from being updated.
101
+ return false ;
102
+ }
103
+
104
+ previousTextLimit = textPosition + ( direction * distance ) / 2 ;
105
+ return true ;
106
+ } ) ,
107
+ ) ;
115
108
}
116
109
117
110
const XAxisRoot = styled ( AxisRoot , {
@@ -208,7 +201,7 @@ function ChartsXAxis(inProps: ChartsXAxisProps) {
208
201
tickLabelPlacement,
209
202
} ) ;
210
203
211
- const xTicksWithDimension = addLabelDimension ( xTicks , {
204
+ const visibleLabels = getVisibleLabels ( xTicks , {
212
205
tickLabelStyle : axisTickLabelProps . style ,
213
206
tickLabelInterval,
214
207
tickLabelMinGap,
@@ -255,8 +248,9 @@ function ChartsXAxis(inProps: ChartsXAxisProps) {
255
248
< Line x1 = { left } x2 = { left + width } className = { classes . line } { ...slotProps ?. axisLine } />
256
249
) }
257
250
258
- { xTicksWithDimension . map (
259
- ( { formattedValue, offset : tickOffset , labelOffset, skipLabel } , index ) => {
251
+ { xTicks . map (
252
+ ( item , index ) => {
253
+ const { formattedValue, offset : tickOffset , labelOffset } = item ;
260
254
const xTickLabel = labelOffset ?? 0 ;
261
255
const yTickLabel = positionSign * ( tickSize + 3 ) ;
262
256
@@ -265,6 +259,8 @@ function ChartsXAxis(inProps: ChartsXAxisProps) {
265
259
{ x : tickOffset + xTickLabel , y : - 1 } ,
266
260
{ direction : 'x' } ,
267
261
) ;
262
+ const skipLabel = ! visibleLabels . has ( item ) ;
263
+
268
264
return (
269
265
< g
270
266
key = { index }
0 commit comments