@@ -1639,6 +1639,25 @@ axes.draw = function(gd, arg, opts) {
1639
1639
* @param {object } ax (full) axis object
1640
1640
* @param {object } opts
1641
1641
* - @param {boolean} skipTitle (set to true to skip axis title draw call)
1642
+ *
1643
+ * Depends on:
1644
+ * - ax._mainSubplot (from linkSubplots)
1645
+ * - ax._mainAxis
1646
+ * - ax._anchorAxis
1647
+ * - ax._subplotsWith
1648
+ * - ax._counterDomainMin, ax._counterDomainMax (optionally, from linkSubplots)
1649
+ * - ax._tickAngles (on redraw only, old value relinked during supplyDefaults)
1650
+ * - ax._mainLinePosition (from lsInner)
1651
+ * - ax._mainMirrorPosition
1652
+ * - ax._linepositions
1653
+ *
1654
+ * Fills in:
1655
+ * - ax._vals:
1656
+ * - ax._gridVals:
1657
+ * - ax._selections:
1658
+ * - ax._tickAngles:
1659
+ * - ax._depth (when required only):
1660
+ * - and calls ax.setScale
1642
1661
*/
1643
1662
axes . drawOne = function ( gd , ax , opts ) {
1644
1663
opts = opts || { } ;
@@ -1673,6 +1692,8 @@ axes.drawOne = function(gd, ax, opts) {
1673
1692
// - stash tickLabels selection, so that drawTitle can use it to scoot title
1674
1693
ax . _selections = { } ;
1675
1694
// stash tick angle (including the computed 'auto' values) per tick-label class
1695
+ // linkup 'previous' tick angles on redraws
1696
+ if ( ax . _tickAngles ) ax . _prevTickAngles = ax . _tickAngles ;
1676
1697
ax . _tickAngles = { } ;
1677
1698
1678
1699
var transFn = axes . makeTransFn ( ax ) ;
@@ -2420,6 +2441,7 @@ axes.drawZeroLine = function(gd, ax, opts) {
2420
2441
* - {number} tickangle
2421
2442
* - {object (optional)} _selections
2422
2443
* - {object} (optional)} _tickAngles
2444
+ * - {object} (optional)} _prevTickAngles
2423
2445
* @param {object } opts
2424
2446
* - {array of object} vals (calcTicks output-like)
2425
2447
* - {d3 selection} layer
@@ -2436,13 +2458,14 @@ axes.drawZeroLine = function(gd, ax, opts) {
2436
2458
axes . drawLabels = function ( gd , ax , opts ) {
2437
2459
opts = opts || { } ;
2438
2460
2461
+ var fullLayout = gd . _fullLayout ;
2439
2462
var axId = ax . _id ;
2440
2463
var axLetter = axId . charAt ( 0 ) ;
2441
2464
var cls = opts . cls || axId + 'tick' ;
2442
2465
var vals = opts . vals ;
2443
2466
var labelFns = opts . labelFns ;
2444
2467
var tickAngle = opts . secondary ? 0 : ax . tickangle ;
2445
- var lastAngle = ( ax . _tickAngles || { } ) [ cls ] ;
2468
+ var prevAngle = ( ax . _prevTickAngles || { } ) [ cls ] ;
2446
2469
2447
2470
var tickLabels = opts . layer . selectAll ( 'g.' + cls )
2448
2471
. data ( ax . showticklabels ? vals : [ ] , tickDataFn ) ;
@@ -2527,17 +2550,17 @@ axes.drawLabels = function(gd, ax, opts) {
2527
2550
// do this without waiting, using the last calculated angle to
2528
2551
// minimize flicker, then do it again when we know all labels are
2529
2552
// there, putting back the prescribed angle to check for overlaps.
2530
- positionLabels ( tickLabels , lastAngle || tickAngle ) ;
2553
+ positionLabels ( tickLabels , ( prevAngle + 1 ) ? prevAngle : tickAngle ) ;
2531
2554
2532
2555
function allLabelsReady ( ) {
2533
2556
return labelsReady . length && Promise . all ( labelsReady ) ;
2534
2557
}
2535
2558
2559
+ var autoangle = null ;
2560
+
2536
2561
function fixLabelOverlaps ( ) {
2537
2562
positionLabels ( tickLabels , tickAngle ) ;
2538
2563
2539
- var autoangle = null ;
2540
-
2541
2564
// check for auto-angling if x labels overlap
2542
2565
// don't auto-angle at all for log axes with
2543
2566
// base and digit format
@@ -2604,19 +2627,36 @@ axes.drawLabels = function(gd, ax, opts) {
2604
2627
positionLabels ( tickLabels , autoangle ) ;
2605
2628
}
2606
2629
}
2607
-
2608
- if ( ax . _tickAngles ) {
2609
- ax . _tickAngles [ cls ] = autoangle === null ?
2610
- ( isNumeric ( tickAngle ) ? tickAngle : 0 ) :
2611
- autoangle ;
2612
- }
2613
2630
}
2614
2631
2615
2632
if ( ax . _selections ) {
2616
2633
ax . _selections [ cls ] = tickLabels ;
2617
2634
}
2618
2635
2619
- var done = Lib . syncOrAsync ( [ allLabelsReady , fixLabelOverlaps ] ) ;
2636
+ var seq = [ allLabelsReady ] ;
2637
+
2638
+ // N.B. during auto-margin redraw, if the axis fixed its label overlaps
2639
+ // by rotating 90 degrees, do not attempt to re-fix its label overlaps
2640
+ // as this can lead to infinite redraw loops!
2641
+ if ( fullLayout . _redrawFromAutoMarginCount && prevAngle === 90 ) {
2642
+ autoangle = 90 ;
2643
+ seq . push ( function ( ) {
2644
+ positionLabels ( tickLabels , prevAngle ) ;
2645
+ } ) ;
2646
+ } else {
2647
+ seq . push ( fixLabelOverlaps ) ;
2648
+ }
2649
+
2650
+ // save current tick angle for future redraws
2651
+ if ( ax . _tickAngles ) {
2652
+ seq . push ( function ( ) {
2653
+ ax . _tickAngles [ cls ] = autoangle === null ?
2654
+ ( isNumeric ( tickAngle ) ? tickAngle : 0 ) :
2655
+ autoangle ;
2656
+ } ) ;
2657
+ }
2658
+
2659
+ var done = Lib . syncOrAsync ( seq ) ;
2620
2660
if ( done && done . then ) gd . _promises . push ( done ) ;
2621
2661
return done ;
2622
2662
} ;
0 commit comments