@@ -1687,19 +1687,13 @@ axes.doTicksSingle = function(gd, arg, skipTitle) {
1687
1687
vals = vals . filter ( ax . _tickFilter ) ;
1688
1688
}
1689
1689
1690
- // remove zero lines, grid lines, and inside ticks if they're within
1691
- // 1 pixel of the end
1690
+ // Remove zero lines, grid lines, and inside ticks if they're within
1691
+ // 1 pixel of the end.
1692
1692
// The key case here is removing zero lines when the axis bound is zero.
1693
- function clipEnds ( d ) {
1694
- var p = ax . l2p ( d . x ) ;
1695
- return ( p > 1 && p < ax . _length - 1 ) ;
1696
- }
1697
- var valsClipped = vals . filter ( clipEnds ) ;
1698
-
1699
- // don't clip angular values
1700
- if ( isAngular ( ax ) ) {
1701
- valsClipped = vals ;
1702
- }
1693
+ // Don't clip angular values.
1694
+ var valsClipped = ax . _valsClipped = isAngular ( ax ) ?
1695
+ vals :
1696
+ vals . filter ( function ( d ) { return clipEnds ( ax , d . x ) ; } ) ;
1703
1697
1704
1698
function drawTicks ( container , tickpath ) {
1705
1699
var ticks = container . selectAll ( 'path.' + tcls )
@@ -2142,69 +2136,17 @@ axes.doTicksSingle = function(gd, arg, skipTitle) {
2142
2136
} ) ;
2143
2137
}
2144
2138
2145
- function traceHasBarsOrFill ( trace , subplot ) {
2146
- if ( trace . visible !== true || trace . xaxis + trace . yaxis !== subplot ) return false ;
2147
- if ( Registry . traceIs ( trace , 'bar' ) && trace . orientation === { x : 'h' , y : 'v' } [ axLetter ] ) return true ;
2148
- return trace . fill && trace . fill . charAt ( trace . fill . length - 1 ) === axLetter ;
2149
- }
2150
-
2151
- function lineNearZero ( ax2 , position ) {
2152
- if ( ! ax2 . showline || ! ax2 . linewidth ) return false ;
2153
- var tolerance = Math . max ( ( ax2 . linewidth + ax . zerolinewidth ) / 2 , 1 ) ;
2154
-
2155
- function closeEnough ( pos2 ) {
2156
- return typeof pos2 === 'number' && Math . abs ( pos2 - position ) < tolerance ;
2157
- }
2158
-
2159
- if ( closeEnough ( ax2 . _mainLinePosition ) || closeEnough ( ax2 . _mainMirrorPosition ) ) {
2160
- return true ;
2161
- }
2162
- var linePositions = ax2 . _linepositions || { } ;
2163
- for ( var k in linePositions ) {
2164
- if ( closeEnough ( linePositions [ k ] [ 0 ] ) || closeEnough ( linePositions [ k ] [ 1 ] ) ) {
2165
- return true ;
2166
- }
2167
- }
2168
- }
2169
-
2170
- function anyCounterAxLineAtZero ( counterAxis , rng ) {
2171
- var mainCounterAxis = counterAxis . _mainAxis ;
2172
- if ( ! mainCounterAxis ) return ;
2173
-
2174
- var zeroPosition = ax . _offset + (
2175
- ( ( Math . abs ( rng [ 0 ] ) < Math . abs ( rng [ 1 ] ) ) === ( axLetter === 'x' ) ) ?
2176
- 0 : ax . _length
2177
- ) ;
2178
-
2179
- var plotinfo = fullLayout . _plots [ counterAxis . _mainSubplot ] ;
2180
- if ( ! ( plotinfo . mainplotinfo || plotinfo ) . overlays . length ) {
2181
- return lineNearZero ( counterAxis , zeroPosition ) ;
2182
- }
2183
-
2184
- var counterLetterAxes = axes . list ( gd , counterLetter ) ;
2185
- for ( var i = 0 ; i < counterLetterAxes . length ; i ++ ) {
2186
- var counterAxis2 = counterLetterAxes [ i ] ;
2187
- if (
2188
- counterAxis2 . _mainAxis === mainCounterAxis &&
2189
- lineNearZero ( counterAxis2 , zeroPosition )
2190
- ) {
2191
- return true ;
2192
- }
2193
- }
2194
- }
2195
-
2196
- function drawGrid ( plotinfo , counteraxis , subplot ) {
2139
+ function drawGrid ( plotinfo , counteraxis ) {
2197
2140
if ( fullLayout . _hasOnlyLargeSploms ) return ;
2198
2141
2199
2142
var gridcontainer = plotinfo . gridlayer . selectAll ( '.' + axid ) ;
2200
2143
var zlcontainer = plotinfo . zerolinelayer ;
2201
- var gridvals = plotinfo [ 'hidegrid' + axLetter ] ? [ ] : valsClipped ;
2202
2144
var gridpath = ax . _gridpath || ( ( axLetter === 'x' ?
2203
2145
( 'M0,' + counteraxis . _offset + 'v' ) :
2204
2146
( 'M' + counteraxis . _offset + ',0h' )
2205
2147
) + counteraxis . _length ) ;
2206
2148
var grid = gridcontainer . selectAll ( 'path.' + gcls )
2207
- . data ( ( ax . showgrid === false ) ? [ ] : gridvals , datafn ) ;
2149
+ . data ( ( ax . showgrid === false ) ? [ ] : valsClipped , datafn ) ;
2208
2150
grid . enter ( ) . append ( 'path' ) . classed ( gcls , 1 )
2209
2151
. classed ( 'crisp' , 1 )
2210
2152
. attr ( 'd' , gridpath )
@@ -2222,24 +2164,8 @@ axes.doTicksSingle = function(gd, arg, skipTitle) {
2222
2164
2223
2165
// zero line
2224
2166
if ( zlcontainer ) {
2225
- var hasBarsOrFill = false ;
2226
- for ( var i = 0 ; i < gd . _fullData . length ; i ++ ) {
2227
- if ( traceHasBarsOrFill ( gd . _fullData [ i ] , subplot ) ) {
2228
- hasBarsOrFill = true ;
2229
- break ;
2230
- }
2231
- }
2232
- var rng = Lib . simpleMap ( ax . range , ax . r2l ) ;
2233
2167
var zlData = { x : 0 , id : axid } ;
2234
-
2235
- var showZl = ( rng [ 0 ] * rng [ 1 ] <= 0 ) && ax . zeroline &&
2236
- ( ax . type === 'linear' || ax . type === '-' ) && gridvals . length &&
2237
- (
2238
- hasBarsOrFill ||
2239
- clipEnds ( zlData ) ||
2240
- ! anyCounterAxLineAtZero ( counteraxis , rng )
2241
- ) ;
2242
-
2168
+ var showZl = axes . shouldShowZeroLine ( gd , ax , counteraxis ) ;
2243
2169
var zl = zlcontainer . selectAll ( 'path.' + zcls )
2244
2170
. data ( showZl ? [ zlData ] : [ ] ) ;
2245
2171
zl . enter ( ) . append ( 'path' ) . classed ( zcls , 1 ) . classed ( 'zl' , 1 )
@@ -2327,6 +2253,96 @@ axes.doTicksSingle = function(gd, arg, skipTitle) {
2327
2253
}
2328
2254
} ;
2329
2255
2256
+ axes . shouldShowZeroLine = function ( gd , ax , counterAxis ) {
2257
+ var rng = Lib . simpleMap ( ax . range , ax . r2l ) ;
2258
+ return (
2259
+ ( rng [ 0 ] * rng [ 1 ] <= 0 ) &&
2260
+ ax . zeroline &&
2261
+ ( ax . type === 'linear' || ax . type === '-' ) &&
2262
+ ax . _valsClipped . length &&
2263
+ (
2264
+ clipEnds ( ax , 0 ) ||
2265
+ ! anyCounterAxLineAtZero ( gd , ax , counterAxis , rng ) ||
2266
+ hasBarsOrFill ( gd , ax )
2267
+ )
2268
+ ) ;
2269
+ } ;
2270
+
2271
+ function clipEnds ( ax , l ) {
2272
+ var p = ax . l2p ( l ) ;
2273
+ return ( p > 1 && p < ax . _length - 1 ) ;
2274
+ }
2275
+
2276
+ function anyCounterAxLineAtZero ( gd , ax , counterAxis , rng ) {
2277
+ var mainCounterAxis = counterAxis . _mainAxis ;
2278
+ if ( ! mainCounterAxis ) return ;
2279
+
2280
+ var fullLayout = gd . _fullLayout ;
2281
+ var axLetter = ax . _id . charAt ( 0 ) ;
2282
+ var counterLetter = axes . counterLetter ( ax . _id ) ;
2283
+
2284
+ var zeroPosition = ax . _offset + (
2285
+ ( ( Math . abs ( rng [ 0 ] ) < Math . abs ( rng [ 1 ] ) ) === ( axLetter === 'x' ) ) ?
2286
+ 0 : ax . _length
2287
+ ) ;
2288
+
2289
+ function lineNearZero ( ax2 ) {
2290
+ if ( ! ax2 . showline || ! ax2 . linewidth ) return false ;
2291
+ var tolerance = Math . max ( ( ax2 . linewidth + ax . zerolinewidth ) / 2 , 1 ) ;
2292
+
2293
+ function closeEnough ( pos2 ) {
2294
+ return typeof pos2 === 'number' && Math . abs ( pos2 - zeroPosition ) < tolerance ;
2295
+ }
2296
+
2297
+ if ( closeEnough ( ax2 . _mainLinePosition ) || closeEnough ( ax2 . _mainMirrorPosition ) ) {
2298
+ return true ;
2299
+ }
2300
+ var linePositions = ax2 . _linepositions || { } ;
2301
+ for ( var k in linePositions ) {
2302
+ if ( closeEnough ( linePositions [ k ] [ 0 ] ) || closeEnough ( linePositions [ k ] [ 1 ] ) ) {
2303
+ return true ;
2304
+ }
2305
+ }
2306
+ }
2307
+
2308
+ var plotinfo = fullLayout . _plots [ counterAxis . _mainSubplot ] ;
2309
+ if ( ! ( plotinfo . mainplotinfo || plotinfo ) . overlays . length ) {
2310
+ return lineNearZero ( counterAxis , zeroPosition ) ;
2311
+ }
2312
+
2313
+ var counterLetterAxes = axes . list ( gd , counterLetter ) ;
2314
+ for ( var i = 0 ; i < counterLetterAxes . length ; i ++ ) {
2315
+ var counterAxis2 = counterLetterAxes [ i ] ;
2316
+ if (
2317
+ counterAxis2 . _mainAxis === mainCounterAxis &&
2318
+ lineNearZero ( counterAxis2 , zeroPosition )
2319
+ ) {
2320
+ return true ;
2321
+ }
2322
+ }
2323
+ }
2324
+
2325
+ function hasBarsOrFill ( gd , ax ) {
2326
+ var fullData = gd . _fullData ;
2327
+ var subplot = ax . _mainSubplot ;
2328
+ var axLetter = ax . _id . charAt ( 0 ) ;
2329
+
2330
+ for ( var i = 0 ; i < fullData . length ; i ++ ) {
2331
+ var trace = fullData [ i ] ;
2332
+
2333
+ if ( trace . visible === true &&
2334
+ ( trace . xaxis + trace . yaxis ) === subplot &&
2335
+ (
2336
+ Registry . traceIs ( trace , 'bar' ) && trace . orientation === { x : 'h' , y : 'v' } [ axLetter ] ||
2337
+ trace . fill && trace . fill . charAt ( trace . fill . length - 1 ) === axLetter
2338
+ )
2339
+ ) {
2340
+ return true ;
2341
+ }
2342
+ }
2343
+ return false ;
2344
+ }
2345
+
2330
2346
/**
2331
2347
* Find all margin pushers for 2D axes and reserve them for later use
2332
2348
* Both label and rangeslider automargin calculations happen later so
0 commit comments