@@ -56,7 +56,8 @@ function getAutoRange(gd, ax) {
56
56
var i , j ;
57
57
var newRange = [ ] ;
58
58
59
- var getPad = makePadFn ( ax ) ;
59
+ var getPadMin = makePadFn ( ax , 0 ) ;
60
+ var getPadMax = makePadFn ( ax , 1 ) ;
60
61
var extremes = concatExtremes ( gd , ax ) ;
61
62
var minArray = extremes . min ;
62
63
var maxArray = extremes . max ;
@@ -97,29 +98,16 @@ function getAutoRange(gd, ax) {
97
98
// don't allow padding to reduce the data to < 10% of the length
98
99
var minSpan = axLen / 10 ;
99
100
100
- // find axis rangebreaks in [v0,v1] and compute its length in value space
101
- var calcBreaksLength = function ( v0 , v1 ) {
102
- var lBreaks = 0 ;
103
- if ( ax . rangebreaks ) {
104
- var rangebreaksOut = ax . locateBreaks ( v0 , v1 ) ;
105
- for ( var i = 0 ; i < rangebreaksOut . length ; i ++ ) {
106
- var brk = rangebreaksOut [ i ] ;
107
- lBreaks += brk . max - brk . min ;
108
- }
109
- }
110
- return lBreaks ;
111
- } ;
112
-
113
101
var mbest = 0 ;
114
102
var minpt , maxpt , minbest , maxbest , dp , dv ;
115
103
116
104
for ( i = 0 ; i < minArray . length ; i ++ ) {
117
105
minpt = minArray [ i ] ;
118
106
for ( j = 0 ; j < maxArray . length ; j ++ ) {
119
107
maxpt = maxArray [ j ] ;
120
- dv = maxpt . val - minpt . val - calcBreaksLength ( minpt . val , maxpt . val ) ;
108
+ dv = maxpt . val - minpt . val - calcBreaksLength ( ax , minpt . val , maxpt . val ) ;
121
109
if ( dv > 0 ) {
122
- dp = axLen - getPad ( minpt ) - getPad ( maxpt ) ;
110
+ dp = axLen - getPadMin ( minpt ) - getPadMax ( maxpt ) ;
123
111
if ( dp > minSpan ) {
124
112
if ( dv / dp > mbest ) {
125
113
minbest = minpt ;
@@ -137,8 +125,8 @@ function getAutoRange(gd, ax) {
137
125
}
138
126
}
139
127
140
- function getMaxPad ( prev , pt ) {
141
- return Math . max ( prev , getPad ( pt ) ) ;
128
+ function maximumPad ( prev , pt ) {
129
+ return Math . max ( prev , getPadMax ( pt ) ) ;
142
130
}
143
131
144
132
if ( minmin === maxmax ) {
@@ -152,7 +140,7 @@ function getAutoRange(gd, ax) {
152
140
// 'tozero' pins 0 to the low end, so follow that.
153
141
newRange = [ 0 , 1 ] ;
154
142
} else {
155
- var maxPad = ( minmin > 0 ? maxArray : minArray ) . reduce ( getMaxPad , 0 ) ;
143
+ var maxPad = ( minmin > 0 ? maxArray : minArray ) . reduce ( maximumPad , 0 ) ;
156
144
// we're pushing a single value away from the edge due to its
157
145
// padding, with the other end clamped at zero
158
146
// 0.5 means don't push it farther than the center.
@@ -173,7 +161,7 @@ function getAutoRange(gd, ax) {
173
161
maxbest = { val : 0 , pad : 0 } ;
174
162
}
175
163
} else if ( nonNegative ) {
176
- if ( minbest . val - mbest * getPad ( minbest ) < 0 ) {
164
+ if ( minbest . val - mbest * getPadMin ( minbest ) < 0 ) {
177
165
minbest = { val : 0 , pad : 0 } ;
178
166
}
179
167
if ( maxbest . val <= 0 ) {
@@ -182,12 +170,12 @@ function getAutoRange(gd, ax) {
182
170
}
183
171
184
172
// in case it changed again...
185
- mbest = ( maxbest . val - minbest . val - calcBreaksLength ( minpt . val , maxpt . val ) ) /
186
- ( axLen - getPad ( minbest ) - getPad ( maxbest ) ) ;
173
+ mbest = ( maxbest . val - minbest . val - calcBreaksLength ( ax , minpt . val , maxpt . val ) ) /
174
+ ( axLen - getPadMin ( minbest ) - getPadMax ( maxbest ) ) ;
187
175
188
176
newRange = [
189
- minbest . val - mbest * getPad ( minbest ) ,
190
- maxbest . val + mbest * getPad ( maxbest )
177
+ minbest . val - mbest * getPadMin ( minbest ) ,
178
+ maxbest . val + mbest * getPadMax ( maxbest )
191
179
] ;
192
180
}
193
181
@@ -197,13 +185,41 @@ function getAutoRange(gd, ax) {
197
185
return Lib . simpleMap ( newRange , ax . l2r || Number ) ;
198
186
}
199
187
188
+ // find axis rangebreaks in [v0,v1] and compute its length in value space
189
+ function calcBreaksLength ( ax , v0 , v1 ) {
190
+ var lBreaks = 0 ;
191
+ if ( ax . rangebreaks ) {
192
+ var rangebreaksOut = ax . locateBreaks ( v0 , v1 ) ;
193
+ for ( var i = 0 ; i < rangebreaksOut . length ; i ++ ) {
194
+ var brk = rangebreaksOut [ i ] ;
195
+ lBreaks += brk . max - brk . min ;
196
+ }
197
+ }
198
+ return lBreaks ;
199
+ }
200
+
200
201
/*
201
202
* calculate the pixel padding for ax._min and ax._max entries with
202
203
* optional extrapad as 5% of the total axis length
203
204
*/
204
- function makePadFn ( ax ) {
205
+ function makePadFn ( ax , max ) {
205
206
// 5% padding for points that specify extrapad: true
206
- var extrappad = ax . _length / 20 ;
207
+ var extrappad = 0.05 * ax . _length ;
208
+
209
+ if (
210
+ ( ax . ticklabelposition || '' ) . indexOf ( 'inside' ) !== - 1 ||
211
+ ( ( ax . _anchorAxis || { } ) . ticklabelposition || '' ) . indexOf ( 'inside' ) !== - 1
212
+ ) {
213
+ var axReverse = ax . autorange === 'reversed' ;
214
+ if ( ! axReverse ) {
215
+ var rng = Lib . simpleMap ( ax . range , ax . r2l ) ;
216
+ axReverse = rng [ 1 ] < rng [ 0 ] ;
217
+ }
218
+ if ( axReverse ) max = ! max ;
219
+ }
220
+
221
+ extrappad = adjustPadForInsideLabelsOnAnchorAxis ( extrappad , ax , max ) ;
222
+ extrappad = adjustPadForInsideLabelsOnThisAxis ( extrappad , ax , max ) ;
207
223
208
224
// domain-constrained axes: base extrappad on the unconstrained
209
225
// domain so it's consistent as the domain changes
@@ -215,6 +231,96 @@ function makePadFn(ax) {
215
231
return function getPad ( pt ) { return pt . pad + ( pt . extrapad ? extrappad : 0 ) ; } ;
216
232
}
217
233
234
+ var TEXTPAD = 3 ;
235
+
236
+ function adjustPadForInsideLabelsOnThisAxis ( extrappad , ax , max ) {
237
+ var ticklabelposition = ax . ticklabelposition || '' ;
238
+ var has = function ( str ) {
239
+ return ticklabelposition . indexOf ( str ) !== - 1 ;
240
+ } ;
241
+
242
+ if ( ! has ( 'inside' ) ) return extrappad ;
243
+ var isTop = has ( 'top' ) ;
244
+ var isLeft = has ( 'left' ) ;
245
+ var isRight = has ( 'right' ) ;
246
+ var isBottom = has ( 'bottom' ) ;
247
+ var isAligned = isBottom || isLeft || isTop || isRight ;
248
+
249
+ if (
250
+ ( max && ( isLeft || isBottom ) ) ||
251
+ ( ! max && ( isRight || isTop ) )
252
+ ) {
253
+ return extrappad ;
254
+ }
255
+
256
+ // increase padding to make more room for inside tick labels of the axis
257
+ var fontSize = ax . tickfont ? ax . tickfont . size : 12 ;
258
+ var isX = ax . _id . charAt ( 0 ) === 'x' ;
259
+ var morePad = ( isX ? 1.2 : 0.6 ) * fontSize ;
260
+
261
+ if ( isAligned ) {
262
+ morePad *= 2 ;
263
+ morePad += ( ax . tickwidth || 0 ) / 2 ;
264
+ }
265
+
266
+ morePad += TEXTPAD ;
267
+
268
+ extrappad = Math . max ( extrappad , morePad ) ;
269
+
270
+ return extrappad ;
271
+ }
272
+
273
+ function adjustPadForInsideLabelsOnAnchorAxis ( extrappad , ax , max ) {
274
+ var anchorAxis = ( ax . _anchorAxis || { } ) ;
275
+ if ( ( anchorAxis . ticklabelposition || '' ) . indexOf ( 'inside' ) !== - 1 ) {
276
+ // increase padding to make more room for inside tick labels of the counter axis
277
+ if ( (
278
+ ! max && (
279
+ anchorAxis . side === 'left' ||
280
+ anchorAxis . side === 'bottom'
281
+ )
282
+ ) || (
283
+ max && (
284
+ anchorAxis . side === 'top' ||
285
+ anchorAxis . side === 'right'
286
+ )
287
+ ) ) {
288
+ var isX = ax . _id . charAt ( 0 ) === 'x' ;
289
+
290
+ var morePad = 0 ;
291
+ if ( anchorAxis . _vals ) {
292
+ var rad = Lib . deg2rad ( anchorAxis . _tickAngles [ anchorAxis . _id + 'tick' ] || 0 ) ;
293
+ var cosA = Math . abs ( Math . cos ( rad ) ) ;
294
+ var sinA = Math . abs ( Math . sin ( rad ) ) ;
295
+
296
+ // use bounding boxes
297
+ anchorAxis . _vals . forEach ( function ( t ) {
298
+ if ( t . bb ) {
299
+ var w = t . bb . width ;
300
+ var h = t . bb . height ;
301
+
302
+ morePad = Math . max ( morePad , isX ?
303
+ Math . max ( w * cosA , h * sinA ) :
304
+ Math . max ( h * cosA , w * sinA )
305
+ ) ;
306
+
307
+ // add extra pad around label
308
+ morePad += 3 ;
309
+ }
310
+ } ) ;
311
+ }
312
+
313
+ if ( anchorAxis . ticks === 'inside' && anchorAxis . ticklabelposition === 'inside' ) {
314
+ morePad += anchorAxis . ticklen || 0 ;
315
+ }
316
+
317
+ extrappad = Math . max ( extrappad , morePad ) ;
318
+ }
319
+ }
320
+
321
+ return extrappad ;
322
+ }
323
+
218
324
function concatExtremes ( gd , ax , noMatch ) {
219
325
var axId = ax . _id ;
220
326
var fullData = gd . _fullData ;
0 commit comments