@@ -234,6 +234,8 @@ proto.updateLayout = function(fullLayout, polarLayout) {
234234 var yOffset2 = _this . yOffset2 = gs . t + gs . h * ( 1 - yDomain2 [ 1 ] ) ;
235235 // circle radius in px
236236 var radius = _this . radius = xLength2 / dxSectorBBox ;
237+ // 'inner' radius in px (when polar.hole is set)
238+ var innerRadius = _this . innerRadius = polarLayout . hole * radius ;
237239 // circle center position in px
238240 var cx = _this . cx = xOffset2 - radius * sectorBBox [ 0 ] ;
239241 var cy = _this . cy = yOffset2 + radius * sectorBBox [ 3 ] ;
@@ -252,7 +254,7 @@ proto.updateLayout = function(fullLayout, polarLayout) {
252254 clockwise : 'bottom'
253255 } [ radialLayout . side ] ,
254256 // spans length 1 radius
255- domain : [ 0 , radius / gs . w ]
257+ domain : [ innerRadius / gs . w , radius / gs . w ]
256258 } ) ;
257259
258260 _this . angularAxis = _this . mockAxis ( fullLayout , polarLayout , angularLayout , {
@@ -282,7 +284,7 @@ proto.updateLayout = function(fullLayout, polarLayout) {
282284 domain : yDomain2
283285 } ) ;
284286
285- var dPath = _this . pathSector ( ) ;
287+ var dPath = _this . pathSubplot ( ) ;
286288
287289 _this . clipPaths . forTraces . select ( 'path' )
288290 . attr ( 'd' , dPath )
@@ -333,9 +335,11 @@ proto.mockCartesianAxis = function(fullLayout, polarLayout, opts) {
333335
334336 ax . setRange = function ( ) {
335337 var sectorBBox = _this . sectorBBox ;
336- var rl = _this . radialAxis . _rl ;
337- var drl = rl [ 1 ] - rl [ 0 ] ;
338338 var ind = bboxIndices [ axId ] ;
339+ var rl = _this . radialAxis . _rl ;
340+ var radius = _this . radius ;
341+ var innerRadius = _this . innerRadius ;
342+ var drl = radius * ( rl [ 1 ] - rl [ 0 ] ) / ( radius - innerRadius ) ;
339343 ax . range = [ sectorBBox [ ind [ 0 ] ] * drl , sectorBBox [ ind [ 1 ] ] * drl ] ;
340344 } ;
341345
@@ -371,6 +375,7 @@ proto.updateRadialAxis = function(fullLayout, polarLayout) {
371375 var gd = _this . gd ;
372376 var layers = _this . layers ;
373377 var radius = _this . radius ;
378+ var innerRadius = _this . innerRadius ;
374379 var cx = _this . cx ;
375380 var cy = _this . cy ;
376381 var radialLayout = polarLayout . radialaxis ;
@@ -392,12 +397,12 @@ proto.updateRadialAxis = function(fullLayout, polarLayout) {
392397
393398 // easier to set rotate angle with custom translate function
394399 ax . _transfn = function ( d ) {
395- return 'translate(' + ax . l2p ( d . x ) + ',0)' ;
400+ return 'translate(' + ( ax . l2p ( d . x ) + innerRadius ) + ',0)' ;
396401 } ;
397402
398403 // set special grid path function
399404 ax . _gridpath = function ( d ) {
400- return _this . pathArc ( ax . r2p ( d . x ) ) ;
405+ return _this . pathArc ( ax . r2p ( d . x ) + innerRadius ) ;
401406 } ;
402407
403408 var newTickLayout = strTickLayout ( radialLayout ) ;
@@ -428,7 +433,7 @@ proto.updateRadialAxis = function(fullLayout, polarLayout) {
428433 . selectAll ( 'path' ) . attr ( 'transform' , null ) ;
429434
430435 updateElement ( layers [ 'radial-line' ] . select ( 'line' ) , radialLayout . showline , {
431- x1 : 0 ,
436+ x1 : innerRadius ,
432437 y1 : 0 ,
433438 x2 : radius ,
434439 y2 : 0 ,
@@ -479,6 +484,7 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) {
479484 var gd = _this . gd ;
480485 var layers = _this . layers ;
481486 var radius = _this . radius ;
487+ var innerRadius = _this . innerRadius ;
482488 var cx = _this . cx ;
483489 var cy = _this . cy ;
484490 var angularLayout = polarLayout . angularaxis ;
@@ -491,11 +497,6 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) {
491497 // 't'ick to 'g'eometric radians is used all over the place here
492498 var t2g = function ( d ) { return ax . t2g ( d . x ) ; } ;
493499
494- // (x,y) at max radius
495- function rad2xy ( rad ) {
496- return [ radius * Math . cos ( rad ) , radius * Math . sin ( rad ) ] ;
497- }
498-
499500 // run rad2deg on tick0 and ditck for thetaunit: 'radians' axes
500501 if ( ax . type === 'linear' && ax . thetaunit === 'radians' ) {
501502 ax . tick0 = rad2deg ( ax . tick0 ) ;
@@ -512,13 +513,17 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) {
512513 }
513514
514515 ax . _transfn = function ( d ) {
516+ var sel = d3 . select ( this ) ;
517+ var hasElement = sel && sel . node ( ) ;
518+
519+ // don't translate grid lines
520+ if ( hasElement && sel . classed ( 'angularaxisgrid' ) ) return '' ;
521+
515522 var rad = t2g ( d ) ;
516- var xy = rad2xy ( rad ) ;
517- var out = strTranslate ( cx + xy [ 0 ] , cy - xy [ 1 ] ) ;
523+ var out = strTranslate ( cx + radius * Math . cos ( rad ) , cy - radius * Math . sin ( rad ) ) ;
518524
519- // must also rotate ticks, but don't rotate labels and grid lines
520- var sel = d3 . select ( this ) ;
521- if ( sel && sel . node ( ) && sel . classed ( 'ticks' ) ) {
525+ // must also rotate ticks, but don't rotate labels
526+ if ( hasElement && sel . classed ( 'ticks' ) ) {
522527 out += strRotate ( - rad2deg ( rad ) ) ;
523528 }
524529
@@ -527,8 +532,10 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) {
527532
528533 ax . _gridpath = function ( d ) {
529534 var rad = t2g ( d ) ;
530- var xy = rad2xy ( rad ) ;
531- return 'M0,0L' + ( - xy [ 0 ] ) + ',' + xy [ 1 ] ;
535+ var cosRad = Math . cos ( rad ) ;
536+ var sinRad = Math . sin ( rad ) ;
537+ return 'M' + [ cx + innerRadius * cosRad , cy - innerRadius * sinRad ] +
538+ 'L' + [ cx + radius * cosRad , cy - radius * sinRad ] ;
532539 } ;
533540
534541 var offset4fontsize = ( angularLayout . ticks !== 'outside' ? 0.7 : 0.5 ) ;
@@ -591,7 +598,7 @@ proto.updateAngularAxis = function(fullLayout, polarLayout) {
591598 _this . vangles = vangles ;
592599
593600 updateElement ( layers [ 'angular-line' ] . select ( 'path' ) , angularLayout . showline , {
594- d : _this . pathSector ( ) ,
601+ d : _this . pathSubplot ( ) ,
595602 transform : strTranslate ( cx , cy )
596603 } )
597604 . attr ( 'stroke-width' , angularLayout . linewidth )
@@ -614,6 +621,7 @@ proto.updateMainDrag = function(fullLayout) {
614621 var MINZOOM = constants . MINZOOM ;
615622 var OFFEDGE = constants . OFFEDGE ;
616623 var radius = _this . radius ;
624+ var innerRadius = _this . innerRadius ;
617625 var cx = _this . cx ;
618626 var cy = _this . cy ;
619627 var cxx = _this . cxx ;
@@ -629,7 +637,7 @@ proto.updateMainDrag = function(fullLayout) {
629637 var mainDrag = dragBox . makeDragger ( layers , 'path' , 'maindrag' , 'crosshair' ) ;
630638
631639 d3 . select ( mainDrag )
632- . attr ( 'd' , _this . pathSector ( ) )
640+ . attr ( 'd' , _this . pathSubplot ( ) )
633641 . attr ( 'transform' , strTranslate ( cx , cy ) ) ;
634642
635643 var dragOpts = {
@@ -727,7 +735,7 @@ proto.updateMainDrag = function(fullLayout) {
727735 function zoomPrep ( ) {
728736 r0 = null ;
729737 r1 = null ;
730- path0 = _this . pathSector ( ) ;
738+ path0 = _this . pathSubplot ( ) ;
731739 dimmed = false ;
732740
733741 var polarLayoutNow = gd . _fullLayout [ _this . id ] ;
@@ -742,7 +750,7 @@ proto.updateMainDrag = function(fullLayout) {
742750 // N.B. this sets scoped 'r0' and 'r1'
743751 // return true if 'valid' zoom distance, false otherwise
744752 function clampAndSetR0R1 ( rr0 , rr1 ) {
745- rr1 = Math . min ( rr1 , radius ) ;
753+ rr1 = Math . max ( Math . min ( rr1 , radius ) , innerRadius ) ;
746754
747755 // starting or ending drag near center (outer edge),
748756 // clamps radial distance at origin (at r=radius)
@@ -1193,15 +1201,13 @@ proto.isPtInside = function(d) {
11931201} ;
11941202
11951203proto . pathArc = function ( r ) {
1196- r = r || this . radius ;
11971204 var sectorInRad = this . sectorInRad ;
11981205 var vangles = this . vangles ;
11991206 var fn = vangles ? helpers . pathPolygon : Lib . pathArc ;
12001207 return fn ( r , sectorInRad [ 0 ] , sectorInRad [ 1 ] , vangles ) ;
12011208} ;
12021209
12031210proto . pathSector = function ( r ) {
1204- r = r || this . radius ;
12051211 var sectorInRad = this . sectorInRad ;
12061212 var vangles = this . vangles ;
12071213 var fn = vangles ? helpers . pathPolygon : Lib . pathSector ;
@@ -1215,6 +1221,12 @@ proto.pathAnnulus = function(r0, r1) {
12151221 return fn ( r0 , r1 , sectorInRad [ 0 ] , sectorInRad [ 1 ] , vangles ) ;
12161222} ;
12171223
1224+ proto . pathSubplot = function ( ) {
1225+ var r0 = this . innerRadius ;
1226+ var r1 = this . radius ;
1227+ return r0 ? this . pathAnnulus ( r0 , r1 ) : this . pathSector ( r1 ) ;
1228+ } ;
1229+
12181230proto . fillViewInitialKey = function ( key , val ) {
12191231 if ( ! ( key in this . viewInitial ) ) {
12201232 this . viewInitial [ key ] = val ;
0 commit comments