@@ -48,7 +48,6 @@ export class CartesianAxis<TData = {}> {
4848 . attr ( 'transform' , this . getAxisTransform ( ) )
4949 . node ( ) ! ;
5050
51- this . maybeTruncateAxisTicks ( axisSvgSelection ) ;
5251 this . addGridLinesIfNeeded ( ) ;
5352
5453 return this ;
@@ -79,17 +78,87 @@ export class CartesianAxis<TData = {}> {
7978 if ( ! this . configuration . tickLabels ) {
8079 selection . selectAll ( '.tick text' ) . remove ( ) ;
8180 }
81+
82+ if ( this . configuration . location === AxisLocation . Bottom ) {
83+ const maxTextTickTextLength = this . getMaxTickTextLength ( selection ) ;
84+ const isLabelRotated = this . rotateAxisTicks ( selection , maxTextTickTextLength ) ;
85+ this . removeOverflowedTicks ( selection , maxTextTickTextLength , isLabelRotated ) ;
86+ } else {
87+ this . maybeTruncateAxisTicks ( selection ) ;
88+ }
89+ }
90+
91+ private getMaxTickTextLength ( axisSvgSelection : Selection < SVGGElement , unknown , null , undefined > ) : number {
92+ const ticksSelection = axisSvgSelection . selectAll ( 'text' ) ;
93+
94+ const allElementLength : number [ ] = [ ] ;
95+
96+ ticksSelection . each ( ( _ , index , nodes ) =>
97+ allElementLength . push ( this . svgUtilService . getElementTextLength ( nodes [ index ] as SVGTextElement ) )
98+ ) ;
99+
100+ return Math . max ( ...allElementLength ) ;
82101 }
83102
84103 private maybeTruncateAxisTicks ( axisSvgSelection : Selection < SVGGElement , unknown , null , undefined > ) : void {
85104 const ticksSelection = axisSvgSelection . selectAll ( 'text' ) ;
86105 const tickBandwidth = Math . abs ( this . scale . getRangeEnd ( ) - this . scale . getRangeStart ( ) ) / ticksSelection . size ( ) ;
87106
88- ticksSelection . each ( ( _datum , index , nodes ) =>
107+ ticksSelection . each ( ( _ , index , nodes ) =>
89108 this . svgUtilService . truncateText ( nodes [ index ] as SVGTextElement , tickBandwidth )
90109 ) ;
91110 }
92111
112+ private getTickTransformValue ( tick : Selection < BaseType , unknown , null , undefined > , axis : 'x' | 'y' ) : number {
113+ const tickTranslateAxis = axis === 'x' ? 0 : 1 ;
114+
115+ const tickTranslateValues = tick . attr ( 'transform' ) . replace ( / .* \( | \) .* / g, '' ) ;
116+ const tickTranslateValue = tickTranslateValues . split ( ',' ) [ tickTranslateAxis ] ?? '0' ;
117+
118+ return parseInt ( tickTranslateValue ) ;
119+ }
120+
121+ private removeOverflowedTicks (
122+ axisSvgSelection : Selection < SVGGElement , unknown , null , undefined > ,
123+ maxTextTickTextLength : number ,
124+ isLabelRotated : boolean
125+ ) : void {
126+ axisSvgSelection . selectAll ( '.tick' ) . each ( ( _ , i , n ) => {
127+ const currentTick = select ( n [ i ] ) ;
128+
129+ const currentTickPosition = this . getTickTransformValue ( currentTick , 'x' ) ;
130+ const isTickOutOfLeftEdge = currentTickPosition < maxTextTickTextLength / 2 ;
131+ const isTickOutOfRightEdge =
132+ this . scale . initData . bounds . endX - ( currentTickPosition + ( isLabelRotated ? 0 : maxTextTickTextLength / 2 ) ) < 0 ;
133+
134+ if ( isTickOutOfLeftEdge || isTickOutOfRightEdge ) {
135+ currentTick . remove ( ) ;
136+ }
137+ } ) ;
138+ }
139+
140+ private rotateAxisTicks (
141+ axisSvgSelection : Selection < SVGGElement , unknown , null , undefined > ,
142+ maxTextLength : number
143+ ) : boolean {
144+ const ticksSelection = axisSvgSelection . selectAll ( 'text' ) ;
145+
146+ const tickBandwidth = ( this . scale . getRangeEnd ( ) - this . scale . getRangeStart ( ) ) / ticksSelection . size ( ) ;
147+
148+ const isLabelRotate = maxTextLength > tickBandwidth ;
149+
150+ if ( isLabelRotate ) {
151+ axisSvgSelection
152+ . selectAll ( '.tick text' )
153+ . style ( 'text-anchor' , 'end' )
154+ . style ( 'font-size' , '100%' )
155+ . attr ( 'y' , '3' )
156+ . attr ( 'transform' , `rotate(-35)` ) ;
157+ }
158+
159+ return isLabelRotate ;
160+ }
161+
93162 private getAxisTransform ( ) : string {
94163 switch ( this . configuration . location ) {
95164 case AxisLocation . Left :
0 commit comments