Skip to content

Commit 0d87312

Browse files
[charts] Improve performance of rendering ticks in x-axis
1 parent 1ffe360 commit 0d87312

File tree

2 files changed

+40
-20
lines changed

2 files changed

+40
-20
lines changed

packages/x-charts/src/ChartsXAxis/ChartsXAxis.tsx

+30-20
Original file line numberDiff line numberDiff line change
@@ -44,44 +44,54 @@ function addLabelDimension(
4444
}: Pick<ChartsXAxisProps, 'tickLabelInterval' | 'tickLabelStyle'> &
4545
Pick<AxisDefaultized, 'reverse'> & { isMounted: boolean },
4646
): (TickItemType & LabelExtraData)[] {
47-
const withDimension = xTicks.map((tick) => {
47+
const getTickSize = (tick: TickItemType) => {
4848
if (!isMounted || tick.formattedValue === undefined) {
49-
return { ...tick, width: 0, height: 0 };
49+
return { width: 0, height: 0 };
5050
}
51+
5152
const tickSizes = getWordsByLines({ style, needsComputation: true, text: tick.formattedValue });
53+
5254
return {
53-
...tick,
5455
width: Math.max(...tickSizes.map((size) => size.width)),
5556
height: Math.max(tickSizes.length * tickSizes[0].height),
5657
};
57-
});
58+
};
5859

59-
if (typeof tickLabelInterval === 'function') {
60-
return withDimension.map((item, index) => ({
61-
...item,
62-
skipLabel: !tickLabelInterval(item.value, index),
63-
}));
64-
}
60+
// FIXME: Add this back
61+
// if (typeof tickLabelInterval === 'function') {
62+
// return withDimension.map((item, index) => ({
63+
// ...item,
64+
// skipLabel: !tickLabelInterval(item.value, index),
65+
// }));
66+
// }
6567

6668
// Filter label to avoid overlap
67-
let currentTextLimit = 0;
6869
let previousTextLimit = 0;
6970
const direction = reverse ? -1 : 1;
70-
return withDimension.map((item, labelIndex) => {
71-
const { width, offset, labelOffset, height } = item;
71+
const minGap = 8;
7272

73-
const distance = getMinXTranslation(width, height, style?.angle);
73+
return xTicks.map((item, labelIndex) => {
74+
const { offset, labelOffset } = item;
7475
const textPosition = offset + labelOffset;
75-
const gapRatio = 1.2; // Ratio applied to the minimal distance to add some margin.
76+
let distance = getMinXTranslation(0, 0, style?.angle);
7677

77-
currentTextLimit = textPosition - (direction * (gapRatio * distance)) / 2;
78-
if (labelIndex > 0 && direction * currentTextLimit < direction * previousTextLimit) {
78+
if (labelIndex > 0 && direction * (textPosition - minGap) < direction * previousTextLimit) {
79+
return { ...item, width: 0, height: 0, skipLabel: true };
80+
}
81+
82+
const { width, height } = getTickSize(item);
83+
84+
distance = getMinXTranslation(width, height, style?.angle);
85+
86+
const currentTextLimit = textPosition - (direction * distance) / 2;
87+
if (labelIndex > 0 && direction * (currentTextLimit - minGap) < direction * previousTextLimit) {
7988
// Except for the first label, we skip all label that overlap with the last accepted.
8089
// Notice that the early return prevents `previousTextLimit` from being updated.
81-
return { ...item, skipLabel: true };
90+
return { ...item, width, height, skipLabel: true };
8291
}
83-
previousTextLimit = textPosition + (direction * (gapRatio * distance)) / 2;
84-
return item;
92+
93+
previousTextLimit = textPosition + (direction * distance) / 2;
94+
return { ...item, width, height };
8595
});
8696
}
8797

packages/x-charts/src/internals/domUtils.ts

+10
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,11 @@ export const getStyleString = (style: React.CSSProperties) =>
9898
);
9999

100100
let domCleanTimeout: NodeJS.Timeout | undefined;
101+
const domResults = { count: 0, time: 0 };
102+
if (typeof window !== 'undefined') {
103+
window.domResults = domResults;
104+
}
105+
101106
/**
102107
*
103108
* @param text The string to estimate
@@ -117,6 +122,9 @@ export const getStringSize = (text: string | number, style: React.CSSProperties
117122
return stringCache.widthCache[cacheKey];
118123
}
119124

125+
domResults.count++;
126+
const startTime = performance.now();
127+
120128
try {
121129
let measurementSpan = document.getElementById(MEASUREMENT_SPAN_ID);
122130
if (measurementSpan === null) {
@@ -158,6 +166,8 @@ export const getStringSize = (text: string | number, style: React.CSSProperties
158166
return result;
159167
} catch {
160168
return { width: 0, height: 0 };
169+
} finally {
170+
domResults.time += performance.now() - startTime;
161171
}
162172
};
163173

0 commit comments

Comments
 (0)