@@ -75,6 +75,15 @@ class LogScale extends IntervalScale<LogScaleSetting> {
7575
7676 const ticks = super . getTicks ( expandToNicedExtent ) ;
7777
78+
79+ // Ticks are created using the nice extent, but that can cause the first and last tick to be well outside the extent
80+ if ( ticks [ 0 ] . value < this . _extent [ 0 ] ) {
81+ ticks [ 0 ] . value = this . _extent [ 0 ] ;
82+ }
83+ if ( ticks [ ticks . length - 1 ] . value > this . _extent [ 1 ] ) {
84+ ticks [ ticks . length - 1 ] . value = this . _extent [ 1 ] ;
85+ }
86+
7887 return zrUtil . map ( ticks , function ( tick ) {
7988 const val = tick . value ;
8089 let powVal = mathPow ( this . base , val ) ;
@@ -93,6 +102,62 @@ class LogScale extends IntervalScale<LogScaleSetting> {
93102 } , this ) ;
94103 }
95104
105+ /**
106+ * Get minor ticks for log scale. Ticks are generated based on a decade so that 5 splits
107+ * between 1 and 10 would be 2, 4, 6, 8 and
108+ * between 5 and 10 would be 6, 8.
109+ * @param splitNumber Get minor ticks number.
110+ * @returns Minor ticks.
111+ */
112+ getMinorTicks ( splitNumber : number ) : number [ ] [ ] {
113+ const ticks = this . getTicks ( true ) ;
114+ const minorTicks = [ ] ;
115+ const negativeMultiplier = this . _isNegative ? - 1 : 1 ;
116+
117+ for ( let i = 1 ; i < ticks . length ; i ++ ) {
118+ const nextTick = ticks [ i ] ;
119+ const prevTick = ticks [ i - 1 ] ;
120+ const logNextTick = Math . ceil ( scaleHelper . absMathLog ( nextTick . value , this . base ) ) ;
121+ const logPrevTick = Math . round ( scaleHelper . absMathLog ( prevTick . value , this . base ) ) ;
122+
123+ const minorTicksGroup : number [ ] = [ ] ;
124+ const tickDiff = logNextTick - logPrevTick ;
125+ const overDecade = tickDiff > 1 ;
126+
127+ if ( overDecade ) {
128+ // For spans over a decade, generate evenly spaced ticks in log space
129+ // For example, between 1 and 100, generate a tick at 10
130+ const step = Math . ceil ( tickDiff / splitNumber ) ;
131+
132+ let minorTickValue = Math . pow ( this . base , logPrevTick + step ) ;
133+ let j = 1 ;
134+ while ( minorTickValue < nextTick . value ) {
135+ minorTicksGroup . push ( minorTickValue ) ;
136+
137+ j ++ ;
138+ minorTickValue = Math . pow ( this . base , logPrevTick + j * step ) * negativeMultiplier ;
139+ }
140+ }
141+ else {
142+ // For spans within a decade, generate linear subdivisions
143+ // For example, between 1 and 10 with splitNumber=5, generate ticks at 2, 4, 6, 8
144+ const maxValue = Math . pow ( this . base , logNextTick ) ;
145+
146+ // Divide the space linearly between min and max
147+ const step = maxValue / splitNumber ;
148+ let minorTickValue = step ;
149+ while ( minorTickValue < nextTick . value ) {
150+ minorTicksGroup . push ( minorTickValue * negativeMultiplier ) ;
151+ minorTickValue += step ;
152+ }
153+ }
154+
155+ minorTicks . push ( minorTicksGroup ) ;
156+ }
157+
158+ return minorTicks ;
159+ }
160+
96161 setExtent ( start : number , end : number ) : void {
97162 // Assume the start and end can be infinity
98163 // log(-Infinity) is NaN, so safe guard here
0 commit comments