@@ -1643,6 +1643,7 @@ axes.draw = function(gd, arg, opts) {
16431643 * - ax._anchorAxis 
16441644 * - ax._subplotsWith 
16451645 * - ax._counterDomainMin, ax._counterDomainMax (optionally, from linkSubplots) 
1646+  * - ax._tickAngles (on redraw only, old value relinked during supplyDefaults) 
16461647 * - ax._mainLinePosition (from lsInner) 
16471648 * - ax._mainMirrorPosition 
16481649 * - ax._linepositions 
@@ -1684,6 +1685,8 @@ axes.drawOne = function(gd, ax, opts) {
16841685    // - stash tickLabels selection, so that drawTitle can use it to scoot title 
16851686    ax . _selections  =  { } ; 
16861687    // stash tick angle (including the computed 'auto' values) per tick-label class 
1688+     // linkup 'previous' tick angles on redraws 
1689+     if ( ax . _tickAngles )  ax . _prevTickAngles  =  ax . _tickAngles ; 
16871690    ax . _tickAngles  =  { } ; 
16881691    // measure [in px] between axis position and outward-most part of bounding box 
16891692    // (touching either the tick label or ticks) 
@@ -1897,12 +1900,12 @@ axes.drawOne = function(gd, ax, opts) {
18971900                if ( llbbox . width  >  0 )  { 
18981901                    var  rExtra  =  llbbox . right  -  ( ax . _offset  +  ax . _length ) ; 
18991902                    if ( rExtra  >  0 )  { 
1900-                         push . x  =  1 ; 
1903+                         push . xr  =  1 ; 
19011904                        push . r  =  rExtra ; 
19021905                    } 
19031906                    var  lExtra  =  ax . _offset  -  llbbox . left ; 
19041907                    if ( lExtra  >  0 )  { 
1905-                         push . x  =  0 ; 
1908+                         push . xl  =  0 ; 
19061909                        push . l  =  lExtra ; 
19071910                    } 
19081911                } 
@@ -1917,12 +1920,12 @@ axes.drawOne = function(gd, ax, opts) {
19171920                if ( llbbox . height  >  0 )  { 
19181921                    var  bExtra  =  llbbox . bottom  -  ( ax . _offset  +  ax . _length ) ; 
19191922                    if ( bExtra  >  0 )  { 
1920-                         push . y  =  0 ; 
1923+                         push . yb  =  0 ; 
19211924                        push . b  =  bExtra ; 
19221925                    } 
19231926                    var  tExtra  =  ax . _offset  -  llbbox . top ; 
19241927                    if ( tExtra  >  0 )  { 
1925-                         push . y  =  1 ; 
1928+                         push . yt  =  1 ; 
19261929                        push . t  =  tExtra ; 
19271930                    } 
19281931                } 
@@ -2400,6 +2403,7 @@ axes.drawZeroLine = function(gd, ax, opts) {
24002403 *  - {number} tickangle 
24012404 *  - {object (optional)} _selections 
24022405 *  - {object} (optional)} _tickAngles 
2406+  *  - {object} (optional)} _prevTickAngles 
24032407 * @param  {object } opts 
24042408 * - {array of object} vals (calcTicks output-like) 
24052409 * - {d3 selection} layer 
@@ -2416,13 +2420,14 @@ axes.drawZeroLine = function(gd, ax, opts) {
24162420axes . drawLabels  =  function ( gd ,  ax ,  opts )  { 
24172421    opts  =  opts  ||  { } ; 
24182422
2423+     var  fullLayout  =  gd . _fullLayout ; 
24192424    var  axId  =  ax . _id ; 
24202425    var  axLetter  =  axId . charAt ( 0 ) ; 
24212426    var  cls  =  opts . cls  ||  axId  +  'tick' ; 
24222427    var  vals  =  opts . vals ; 
24232428    var  labelFns  =  opts . labelFns ; 
24242429    var  tickAngle  =  opts . secondary  ? 0  : ax . tickangle ; 
2425-     var  lastAngle  =  ( ax . _tickAngles  ||  { } ) [ cls ] ; 
2430+     var  prevAngle  =  ( ax . _prevTickAngles  ||  { } ) [ cls ] ; 
24262431
24272432    var  tickLabels  =  opts . layer . selectAll ( 'g.'  +  cls ) 
24282433        . data ( ax . showticklabels  ? vals  : [ ] ,  tickDataFn ) ; 
@@ -2507,17 +2512,17 @@ axes.drawLabels = function(gd, ax, opts) {
25072512    // do this without waiting, using the last calculated angle to 
25082513    // minimize flicker, then do it again when we know all labels are 
25092514    // there, putting back the prescribed angle to check for overlaps. 
2510-     positionLabels ( tickLabels ,  lastAngle   ||  tickAngle ) ; 
2515+     positionLabels ( tickLabels ,  ( prevAngle   +   1 )  ?  prevAngle  :  tickAngle ) ; 
25112516
25122517    function  allLabelsReady ( )  { 
25132518        return  labelsReady . length  &&  Promise . all ( labelsReady ) ; 
25142519    } 
25152520
2521+     var  autoangle  =  null ; 
2522+ 
25162523    function  fixLabelOverlaps ( )  { 
25172524        positionLabels ( tickLabels ,  tickAngle ) ; 
25182525
2519-         var  autoangle  =  null ; 
2520- 
25212526        // check for auto-angling if x labels overlap 
25222527        // don't auto-angle at all for log axes with 
25232528        // base and digit format 
@@ -2584,19 +2589,36 @@ axes.drawLabels = function(gd, ax, opts) {
25842589                positionLabels ( tickLabels ,  autoangle ) ; 
25852590            } 
25862591        } 
2587- 
2588-         if ( ax . _tickAngles )  { 
2589-             ax . _tickAngles [ cls ]  =  autoangle  ===  null  ?
2590-                 ( isNumeric ( tickAngle )  ? tickAngle  : 0 )  :
2591-                 autoangle ; 
2592-         } 
25932592    } 
25942593
25952594    if ( ax . _selections )  { 
25962595        ax . _selections [ cls ]  =  tickLabels ; 
25972596    } 
25982597
2599-     var  done  =  Lib . syncOrAsync ( [ allLabelsReady ,  fixLabelOverlaps ] ) ; 
2598+     var  seq  =  [ allLabelsReady ] ; 
2599+ 
2600+     // N.B. during auto-margin redraws, if the axis fixed its label overlaps 
2601+     // by rotating 90 degrees, do not attempt to re-fix its label overlaps 
2602+     // as this can lead to infinite redraw loops! 
2603+     if ( ax . automargin  &&  fullLayout . _redrawFromAutoMarginCount  &&  prevAngle  ===  90 )  { 
2604+         autoangle  =  90 ; 
2605+         seq . push ( function ( )  { 
2606+             positionLabels ( tickLabels ,  prevAngle ) ; 
2607+         } ) ; 
2608+     }  else  { 
2609+         seq . push ( fixLabelOverlaps ) ; 
2610+     } 
2611+ 
2612+     // save current tick angle for future redraws 
2613+     if ( ax . _tickAngles )  { 
2614+         seq . push ( function ( )  { 
2615+             ax . _tickAngles [ cls ]  =  autoangle  ===  null  ?
2616+                 ( isNumeric ( tickAngle )  ? tickAngle  : 0 )  :
2617+                 autoangle ; 
2618+         } ) ; 
2619+     } 
2620+ 
2621+     var  done  =  Lib . syncOrAsync ( seq ) ; 
26002622    if ( done  &&  done . then )  gd . _promises . push ( done ) ; 
26012623    return  done ; 
26022624} ; 
0 commit comments