diff --git a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts index 29c7dc8b42f..d12ff095b6a 100644 --- a/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts +++ b/packages/grafana-ui/src/components/uPlot/config/UPlotAxisBuilder.ts @@ -143,8 +143,8 @@ function calculateAxisSize(self: uPlot, values: string[], axisIdx: number) { if (axis.side === 2) { axisSize += axis!.gap! + fontSize; } else if (values?.length) { - let longestValue = values.reduce((acc, value) => (value.length > acc.length ? value : acc), ''); - axisSize += axis!.gap! + axis!.labelGap! + measureText('0'.repeat(longestValue.length), fontSize).width; + let maxTextWidth = values.reduce((acc, value) => Math.max(acc, measureText(value, fontSize).width), 0); + axisSize += axis!.gap! + axis!.labelGap! + maxTextWidth; } return Math.ceil(axisSize); diff --git a/packages/grafana-ui/src/utils/measureText.ts b/packages/grafana-ui/src/utils/measureText.ts index 2b20a5c8ae6..caf76afb1de 100644 --- a/packages/grafana-ui/src/utils/measureText.ts +++ b/packages/grafana-ui/src/utils/measureText.ts @@ -1,19 +1,12 @@ -let canvas: HTMLCanvasElement | null = null; -const cache: Record = {}; +const context = document.createElement('canvas').getContext('2d')!; +const cache = new Map(); +const cacheLimit = 500; +let ctxFontStyle = ''; /** * @internal */ export function getCanvasContext() { - if (canvas === null) { - canvas = document.createElement('canvas'); - } - - const context = canvas.getContext('2d'); - if (!context) { - throw new Error('Could not create context'); - } - return context; } @@ -23,18 +16,24 @@ export function getCanvasContext() { export function measureText(text: string, fontSize: number): TextMetrics { const fontStyle = `${fontSize}px 'Roboto'`; const cacheKey = text + fontStyle; - const fromCache = cache[cacheKey]; + const fromCache = cache.get(cacheKey); if (fromCache) { return fromCache; } - const context = getCanvasContext(); + if (ctxFontStyle !== fontStyle) { + context.font = ctxFontStyle = fontStyle; + } - context.font = fontStyle; const metrics = context.measureText(text); - cache[cacheKey] = metrics; + if (cache.size === cacheLimit) { + cache.clear(); + } + + cache.set(cacheKey, metrics); + return metrics; }