@@ -75,6 +75,15 @@ class LogScale extends IntervalScale<LogScaleSetting> {
75
75
76
76
const ticks = super . getTicks ( expandToNicedExtent ) ;
77
77
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
+
78
87
return zrUtil . map ( ticks , function ( tick ) {
79
88
const val = tick . value ;
80
89
let powVal = mathPow ( this . base , val ) ;
@@ -93,6 +102,62 @@ class LogScale extends IntervalScale<LogScaleSetting> {
93
102
} , this ) ;
94
103
}
95
104
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
+
96
161
setExtent ( start : number , end : number ) : void {
97
162
// Assume the start and end can be infinity
98
163
// log(-Infinity) is NaN, so safe guard here
0 commit comments