@@ -23,18 +23,57 @@ export interface YAxisConfig {
2323 max ?: number ;
2424}
2525
26- // Average character width in pixels (approximate for typical UI fonts)
27- const AVG_CHAR_WIDTH = 7 ;
28- // Base padding for axis labels (spacing, axis line, etc.)
29- const AXIS_LABEL_PADDING = 12 ;
26+ // Character width multipliers (approximate for typical UI fonts)
27+ const CHAR_WIDTH_BASE = 8 ;
28+ const CHAR_WIDTH_MULTIPLIERS = {
29+ dot : 0.5 , // Dots and periods are very narrow
30+ uppercase : 0.9 ,
31+ lowercase : 0.65 , // Lowercase letters slightly narrower
32+ digit : 0.7 ,
33+ symbol : 0.7 , // Symbols like %, $, etc.
34+ space : 0.5 , // Spaces
35+ } ;
36+ const AXIS_LABEL_PADDING = 14 ;
37+
38+ /**
39+ * Calculate the width of a single character based on its type
40+ */
41+ function getCharWidth ( char ?: string ) : number {
42+ if ( ! char || char . length === 0 ) {
43+ return 0 ;
44+ }
45+
46+ if ( char === '.' || char === ',' || char === ':' ) {
47+ return CHAR_WIDTH_BASE * CHAR_WIDTH_MULTIPLIERS . dot ;
48+ }
49+ if ( char === ' ' ) {
50+ return CHAR_WIDTH_BASE * CHAR_WIDTH_MULTIPLIERS . space ;
51+ }
52+ if ( char >= 'A' && char <= 'Z' ) {
53+ return CHAR_WIDTH_BASE * CHAR_WIDTH_MULTIPLIERS . uppercase ;
54+ }
55+ if ( char >= 'a' && char <= 'z' ) {
56+ return CHAR_WIDTH_BASE * CHAR_WIDTH_MULTIPLIERS . lowercase ;
57+ }
58+ if ( char >= '0' && char <= '9' ) {
59+ return CHAR_WIDTH_BASE * CHAR_WIDTH_MULTIPLIERS . digit ;
60+ }
61+ // Symbols like %, $, -, +, etc.
62+ return CHAR_WIDTH_BASE * CHAR_WIDTH_MULTIPLIERS . symbol ;
63+ }
3064
3165/**
3266 * Estimate the pixel width needed for an axis label based on the formatted max value.
3367 * This provides dynamic spacing that adapts to the actual data scale.
3468 */
3569function estimateLabelWidth ( format : FormatOptions | undefined , maxValue : number ) : number {
3670 const formattedLabel = formatValue ( maxValue , format ) ;
37- return formattedLabel . length * AVG_CHAR_WIDTH + AXIS_LABEL_PADDING ;
71+ // Calculate width based on individual character types
72+ let totalWidth = 0 ;
73+ for ( let i = 0 ; i < formattedLabel . length ; i ++ ) {
74+ totalWidth += getCharWidth ( formattedLabel [ i ] ) ;
75+ }
76+ return totalWidth ;
3877}
3978
4079/*
@@ -92,12 +131,6 @@ export function getFormattedMultipleYAxes(
92131
93132 // Additional Y axes (right side) for each unique format
94133 additionalFormats . forEach ( ( format , index ) => {
95- // For subsequent axes, add the width of the previous axis's labels
96- if ( index > 0 && maxValues ) {
97- const prevMaxValue = maxValues [ index - 1 ] ?? 1000 ;
98- cumulativeOffset += estimateLabelWidth ( additionalFormats [ index - 1 ] , prevMaxValue ) ;
99- }
100-
101134 const rightAxisConfig : YAXisComponentOption = {
102135 type : 'value' ,
103136 position : 'right' ,
@@ -115,6 +148,10 @@ export function getFormattedMultipleYAxes(
115148 show : baseAxis ?. show ,
116149 } ;
117150 axes . push ( rightAxisConfig ) ;
151+ // For subsequent axes, add the width of the previous axis's labels
152+ if ( maxValues ) {
153+ cumulativeOffset += estimateLabelWidth ( format , maxValues [ index ] ?? 1000 ) + AXIS_LABEL_PADDING ;
154+ }
118155 } ) ;
119156
120157 return axes ;
0 commit comments