diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts index b7ab4ca1406..69987951347 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/Orchestrator.ts @@ -17,8 +17,8 @@ export class Orchestrator { this.componentStore = { title: getChartTitleComponent(chartConfig, chartData), plot: getPlotComponent(chartConfig, chartData), - xAxis: getAxis(chartData.xAxis, chartConfig.xAxis), - yAxis: getAxis(chartData.yAxis, chartConfig.yAxis), + xAxis: getAxis(chartData.xAxis, chartConfig.xAxis, chartConfig.fontFamily), + yAxis: getAxis(chartData.yAxis, chartConfig.yAxis, chartConfig.fontFamily), }; } diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/TextDimensionCalculator.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/TextDimensionCalculator.ts index c7a252609d6..c717163ce21 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/TextDimensionCalculator.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/TextDimensionCalculator.ts @@ -1,7 +1,7 @@ import { Dimension } from './Interfaces.js'; export interface ITextDimensionCalculator { - getDimension(texts: string[], fontSize: number, fontFamily?: string ): Dimension; + getDimension(texts: string[], fontSize: number, fontFamily?: string): Dimension; } export class TextDimensionCalculator implements ITextDimensionCalculator { @@ -13,3 +13,57 @@ export class TextDimensionCalculator implements ITextDimensionCalculator { }; } } + +export class TextDimensionCalculatorWithFont implements ITextDimensionCalculator { + private container: HTMLSpanElement | null = null; + private hiddenElementId = 'mermaid-text-dimension-calculator'; + constructor(fontFamily?: string) { + if (document) { + let parentContainer = document.getElementById(this.hiddenElementId); + if (!parentContainer) { + parentContainer = document.createElement('div'); + parentContainer.id = this.hiddenElementId; + parentContainer.style.position = 'absolute'; + parentContainer.style.top = '-100px'; + parentContainer.style.left = '0px'; + parentContainer.style.visibility = 'hidden'; + document.body.append(parentContainer); + } + const fontClassName = `font-${fontFamily}`; + const prevContainerAvailable = parentContainer.getElementsByClassName(fontClassName); + if (prevContainerAvailable.length > 0) { + this.container = prevContainerAvailable.item(0) as HTMLSpanElement; + } else { + this.container = document.createElement('div'); + this.container.className = fontClassName; + if (fontFamily) { + this.container.style.fontFamily = fontFamily; + } + parentContainer.append(this.container); + } + } + } + getDimension(texts: string[], fontSize: number): Dimension { + if (!this.container) { + return { + width: texts.reduce((acc, cur) => Math.max(cur.length, acc), 0) * fontSize, + height: fontSize, + }; + } + + const dimension: Dimension = { + width: 0, + height: 0, + }; + + this.container.style.fontSize = `${fontSize}px`; + + for (let t of texts) { + this.container.innerHTML = t; + const bbox = this.container.getBoundingClientRect(); + dimension.width = Math.max(dimension.width, bbox.width); + dimension.height = Math.max(dimension.height, bbox.height); + } + return dimension; + } +} diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts index ae70994717a..3cad0dea053 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/ChartTitle.ts @@ -1,13 +1,13 @@ -import { ITextDimensionCalculator, TextDimensionCalculator } from '../TextDimensionCalculator.js'; +import { XYChartConfig } from '../../../../config.type.js'; import { - XYChartData, - Dimension, - BoundingRect, - DrawableElem, - Point, + BoundingRect, + ChartComponent, + Dimension, + DrawableElem, + Point, + XYChartData, } from '../Interfaces.js'; -import { ChartComponent } from '../Interfaces.js'; -import { XYChartConfig } from '../../../../config.type.js'; +import { ITextDimensionCalculator, TextDimensionCalculatorWithFont } from '../TextDimensionCalculator.js'; export class ChartTitle implements ChartComponent { private boundingRect: BoundingRect; @@ -75,6 +75,6 @@ export function getChartTitleComponent( chartConfig: XYChartConfig, chartData: XYChartData ): ChartComponent { - const textDimensionCalculator = new TextDimensionCalculator(); + const textDimensionCalculator = new TextDimensionCalculatorWithFont(chartConfig.fontFamily); return new ChartTitle(textDimensionCalculator, chartConfig, chartData); } diff --git a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts index 7888ac286be..9953679f018 100644 --- a/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts +++ b/packages/mermaid/src/diagrams/xychart/chartBuilder/components/axis/index.ts @@ -1,12 +1,12 @@ +import { XYChartAxisConfig } from '../../../../../config.type.js'; import { AxisDataType, + ChartComponent, isBandAxisData, } from '../../Interfaces.js'; -import { TextDimensionCalculator } from '../../TextDimensionCalculator.js'; -import { ChartComponent } from '../../Interfaces.js'; +import { TextDimensionCalculatorWithFont } from '../../TextDimensionCalculator.js'; import { BandAxis } from './BandAxis.js'; import { LinearAxis } from './LinearAxis.js'; -import { XYChartAxisConfig } from '../../../../../config.type.js'; export type AxisPosition = 'left' | 'right' | 'top' | 'bottom'; @@ -18,8 +18,8 @@ export interface IAxis extends ChartComponent { setRange(range: [number, number]): void; } -export function getAxis(data: AxisDataType, axisConfig: XYChartAxisConfig): IAxis { - const textDimansionCalculator = new TextDimensionCalculator(); +export function getAxis(data: AxisDataType, axisConfig: XYChartAxisConfig, fontFamily?: string): IAxis { + const textDimansionCalculator = new TextDimensionCalculatorWithFont(fontFamily); if (isBandAxisData(data)) { return new BandAxis(axisConfig, data.categories, data.title, textDimansionCalculator); }