From 150ccd351e7636360b0539b49b06002ca54281d2 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 6 May 2025 11:19:54 +0200 Subject: [PATCH 01/12] Fixes #7416 Hidden ticklabels don't take up space anymore. --- src/plots/cartesian/axes.js | 15 ++++++++- test/image/mocks/zz-label-spacing.json | 44 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test/image/mocks/zz-label-spacing.json diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 84ebe5b3bb1..dad5a4bbb36 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -3915,11 +3915,24 @@ axes.drawLabels = function(gd, ax, opts) { } } + function removeHiddenLabels() { + // Remove all hidden labels to prevent them from affecting the layout. + tickLabels.each(function(d) { + var thisLabel = d3.select(this); + var textNode = thisLabel.select('text').node(); + var opacity = window.getComputedStyle(textNode).opacity; + if (opacity == '0') { + thisLabel.select('text').text(''); + d3.select(textNode).text(''); + } + }); + } + if(ax._selections) { ax._selections[cls] = tickLabels; } - var seq = [allLabelsReady]; + var seq = [allLabelsReady, removeHiddenLabels]; // N.B. during auto-margin redraws, if the axis fixed its label overlaps // by rotating 90 degrees, do not attempt to re-fix its label overlaps diff --git a/test/image/mocks/zz-label-spacing.json b/test/image/mocks/zz-label-spacing.json new file mode 100644 index 00000000000..310dea817b9 --- /dev/null +++ b/test/image/mocks/zz-label-spacing.json @@ -0,0 +1,44 @@ +{ + "data": [ + { + "x": ["A", "B", "C"], + "y": [0, 40, 80], + "type": "scatter" + }, + { + "x": ["A", "B", "C"], + "y": [0, 40, 80], + "type": "scatter", + "xaxis": "x2", + "yaxis": "y2" + } + ], + "layout": { + "title": { + "text": "The vertical grid lines in the subplots should be aligned." + }, + "width": 600, + "xaxis": { + "anchor": "y" + }, + "xaxis2": { + "anchor": "y2" + }, + "yaxis": { + "range": [0, 80], + "dtick": 20, + "side": "right", + "ticklabelposition": "inside", + "anchor": "x", + "domain": [0, 0.45] + }, + "yaxis2": { + "range": [0, 100], + "dtick": 20, + "side": "right", + "ticklabelposition": "inside", + "anchor": "x2", + "domain": [0.55, 1] + } + } +} From 684d05c0a74d6596c6b5c15bd1cd1b2ccd36cc31 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 6 May 2025 12:31:09 +0200 Subject: [PATCH 02/12] Update some tests in axes_test.js, because hidden labels no longer take up space. Also use floating point comparison in "Test axes minor ticks" --- test/jasmine/tests/axes_test.js | 47 +++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index e42cf4a60df..4283bd8ac57 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1696,7 +1696,8 @@ describe('Test axes', function() { return Plotly.relayout(gd, 'xaxis.autorange', true); }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.37, 3.22], 1); + + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.27, 3.23], 1); }) .then(done, done.fail); }); @@ -1721,13 +1722,13 @@ describe('Test axes', function() { width: 600, height: 600 }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.110, 2]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.13, 2]); return Plotly.relayout(gd, { 'xaxis.insiderange': [1, 3] }); }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.889, 3]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.866, 3]); }).then(done, done.fail); }); }); @@ -4907,32 +4908,32 @@ describe('Test axes', function() { }) .then(function() { _assert('on labels (defaults)', { - ticks: [110.75, 350, 589.25], - gridLines: [110.75, 350, 589.25], + ticks: [108.75, 348, 587.25], + gridLines: [108.75, 348, 587.25], tickLabels: [106.421, 345.671, 585.25] }); return Plotly.relayout(gd, 'xaxis.tickson', 'boundaries'); }) .then(function() { _assert('inside on boundaries', { - ticks: [230.369, 469.619], // N.B. first and last tick are clipped - gridLines: [230.369, 469.619], + ticks: [228.367, 467.617], // N.B. first and last tick are clipped + gridLines: [228.367, 467.617], tickLabels: [106.421875, 345.671875, 585.25] }); return Plotly.relayout(gd, 'xaxis.ticks', 'outside'); }) .then(function() { _assert('outside on boundaries', { - ticks: [230.369, 469.619], - gridLines: [230.369, 469.619], + ticks: [228.367, 467.617], + gridLines: [228.367, 467.617], tickLabels: [106.421875, 345.671875, 585.25] }); return Plotly.restyle(gd, 'x', [[1, 2, 1]]); }) .then(function() { _assert('fallback to *labels* on non-category axes', { - ticks: [110.75, 206.449, 302.149, 397.85, 493.549, 589.25], - gridLines: [110.75, 206.449, 302.149, 397.85, 493.549, 589.25], + ticks: [108.75, 204.433, 300.133, 395.85, 491.533, 587.25], + gridLines: [108.75, 204.433, 300.133, 395.85, 491.533, 587.25], tickLabels: [106.421, 197.121, 292.821, 388.521, 484.221, 584.921] }); }) @@ -6901,6 +6902,18 @@ describe('Test axes', function() { expect(positions).toEqual(expPositions); } + function _assertClose(expPositions) { + var ax = gd._fullLayout.xaxis; + + // minor positions + var positions = + ax._vals + .filter(function(d) { return d.minor; }) + .map(function(d) { return d.x; }); + + expect(positions).toBeCloseToArray(expPositions); + } + it('minor tickvals', function(done) { Plotly.newPlot(gd, { data: [{ @@ -7127,7 +7140,7 @@ describe('Test axes', function() { } }) .then(function() { - _assert([ -0.22184874961635648, -0.1549019599857433, -0.09691001300805657, -0.04575749056067513, 0.4771212547196623, 0.6020599913279623, 0.7781512503836435, 0.8450980400142567, 0.9030899869919434, 0.9542425094393249, 1.4771212547196624, 1.6020599913279623, 1.7781512503836434, 1.8450980400142567, 1.9030899869919433, 1.9542425094393248, 2.477121254719662, 2.6020599913279625, 2.7781512503836434, 2.845098040014257, 2.9030899869919433, 2.9542425094393248, 3.477121254719662, 3.6020599913279625, 3.7781512503836434, 3.845098040014257, 3.9030899869919433, 3.9542425094393248 ]); + _assertClose([ -0.22184874961635648, -0.1549019599857433, -0.09691001300805657, -0.04575749056067513, 0.4771212547196623, 0.6020599913279623, 0.7781512503836435, 0.8450980400142567, 0.9030899869919434, 0.9542425094393249, 1.4771212547196624, 1.6020599913279623, 1.7781512503836434, 1.8450980400142567, 1.9030899869919433, 1.9542425094393248, 2.477121254719662, 2.6020599913279625, 2.7781512503836434, 2.845098040014257, 2.9030899869919433, 2.9542425094393248, 3.477121254719662, 3.6020599913279625, 3.7781512503836434, 3.845098040014257, 3.9030899869919433, 3.9542425094393248 ]); }) .then(done, done.fail); }); @@ -7169,7 +7182,7 @@ describe('Test axes', function() { } }) .then(function() { - _assert([ -0.017728766960431602, -0.00877392430750515, 0.008600171761917567, 0.017033339298780367, 0.025305865264770258, 0.03342375548694973, 0.049218022670181646, 0.056904851336472634, 0.06445798922691853, 0.07188200730612543, 0.08635983067474828, 0.09342168516223513, 0.10037054511756296, 0.10720996964786844, 0.12057393120584996, 0.1271047983648077, 0.13353890837021762, 0.13987908640123659, 0.15228834438305658, 0.15836249209524975, 0.1643528557844372, 0.17026171539495752, 0.18184358794477265, 0.18752072083646318, 0.1931245983544617, 0.1986570869544227, 0.20951501454263102, 0.21484384804769796, 0.22010808804005513, 0.22530928172586287, 0.23552844690754896, 0.24054924828259974, 0.24551266781414988, 0.250420002308894, 0.2600713879850748, 0.2648178230095364, 0.26951294421791616, 0.2741578492636797, 0.28330122870354935, 0.2878017299302258, 0.29225607135647574, 0.29666519026153076, 0.30535136944662333, 0.3096301674258983, 0.31386722036915293, 0.31806333496276107 ]); + _assertClose([ -0.017728766960431602, -0.00877392430750515, 0.008600171761917567, 0.017033339298780367, 0.025305865264770258, 0.03342375548694973, 0.049218022670181646, 0.056904851336472634, 0.06445798922691853, 0.07188200730612543, 0.08635983067474828, 0.09342168516223513, 0.10037054511756296, 0.10720996964786844, 0.12057393120584996, 0.1271047983648077, 0.13353890837021762, 0.13987908640123659, 0.15228834438305658, 0.15836249209524975, 0.1643528557844372, 0.17026171539495752, 0.18184358794477265, 0.18752072083646318, 0.1931245983544617, 0.1986570869544227, 0.20951501454263102, 0.21484384804769796, 0.22010808804005513, 0.22530928172586287, 0.23552844690754896, 0.24054924828259974, 0.24551266781414988, 0.250420002308894, 0.2600713879850748, 0.2648178230095364, 0.26951294421791616, 0.2741578492636797, 0.28330122870354935, 0.2878017299302258, 0.29225607135647574, 0.29666519026153076, 0.30535136944662333, 0.3096301674258983, 0.31386722036915293, 0.31806333496276107 ]); }) .then(done, done.fail); }); @@ -7191,7 +7204,7 @@ describe('Test axes', function() { } }) .then(function() { - _assert([ -0.30102999566398125, 0.30102999566398114, 0.6989700043360187, 1.3010299956639813, 1.6989700043360187, 2.3010299956639813, 2.6989700043360187, 3.3010299956639813, 3.6989700043360187, 4.301029995663981, 4.698970004336019, 5.301029995663981, 5.698970004336019, 6.301029995663981, 6.698970004336019, 7.301029995663981 ]); + _assertClose([ -0.30102999566398125, 0.30102999566398114, 0.6989700043360187, 1.3010299956639813, 1.6989700043360187, 2.3010299956639813, 2.6989700043360187, 3.3010299956639813, 3.6989700043360187, 4.301029995663981, 4.698970004336019, 5.301029995663981, 5.698970004336019, 6.301029995663981, 6.698970004336019, 7.301029995663981 ]); }) .then(done, done.fail); }); @@ -7213,7 +7226,7 @@ describe('Test axes', function() { } }) .then(function() { - _assert([ 0.17609125905568124, 0.3979400086720376, 0.5440680443502756, 0.6532125137753436, 0.7403626894942437, 0.8129133566428552, 0.8750612633916998, 0.9294189257142923, 0.9777236052888472, 1.0211892990699374, 1.0413926851582243, 1.0606978403536107 ]); + _assertClose([ 0.17609125905568124, 0.3979400086720376, 0.5440680443502756, 0.6532125137753436, 0.7403626894942437, 0.8129133566428552, 0.8750612633916998, 0.9294189257142923, 0.9777236052888472, 1.0211892990699374, 1.0413926851582243, 1.0606978403536107 ]); }) .then(done, done.fail); }); @@ -8139,11 +8152,11 @@ describe('more react tests', function() { Plotly.newPlot(gd, fig1) .then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.110, 2]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.134, 2]); return Plotly.react(gd, fig2); }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.164, 2]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.192, 2]); }).then(done, done.fail); }); }); From a287e906f0312f930ca3389429215edb5f6780ec Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 6 May 2025 13:29:41 +0200 Subject: [PATCH 03/12] Add draftlog for 7417 --- draftlogs/7417_fix.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 draftlogs/7417_fix.md diff --git a/draftlogs/7417_fix.md b/draftlogs/7417_fix.md new file mode 100644 index 00000000000..62aef9598f7 --- /dev/null +++ b/draftlogs/7417_fix.md @@ -0,0 +1 @@ +- Fix hidden ticklabels taking up plot space [[#7417](https://github.com/plotly/plotly.js/pull/7417)] From e157374597f1a377462b11a9257716ec03fac304 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Fri, 9 May 2025 11:10:21 +0200 Subject: [PATCH 04/12] Instead of removing text of hidden ticklabels, just set their display mode to none. This is actually what we want: the label should not be visible and not take up space. --- src/plots/cartesian/axes.js | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index dad5a4bbb36..9d55139e45f 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -3648,7 +3648,7 @@ axes.drawLabels = function(gd, ax, opts) { 'text-anchor': anchor }); - thisText.style('opacity', 1); // visible + thisText.style('display', null); // visible if(ax._adjustTickLabelsOverflow) { ax._adjustTickLabelsOverflow(); @@ -3706,9 +3706,9 @@ axes.drawLabels = function(gd, ax, opts) { var t = thisLabel.select('text'); if(adjust) { - if(hideOverflow) t.style('opacity', 0); // hidden + if(hideOverflow) t.style('display', 'none'); // hidden } else { - t.style('opacity', 1); // visible + t.style('display', null); // visible if(side === 'bottom' || side === 'right') { visibleLabelMin = Math.min(visibleLabelMin, isX ? bb.top : bb.left); @@ -3783,7 +3783,7 @@ axes.drawLabels = function(gd, ax, opts) { q > ax['_visibleLabelMin_' + anchorAx._id] ) { t.style('display', 'none'); // hidden - } else if(e.K === 'tick' && !idx) { + } else if(e.K === 'tick' && !idx && t.style('display') != 'none') { t.style('display', null); // visible } }); @@ -3807,6 +3807,7 @@ axes.drawLabels = function(gd, ax, opts) { var autoangle = null; function fixLabelOverlaps() { + console.log("fix label overlaps!"); positionLabels(tickLabels, tickAngle); // check for auto-angling if x labels overlap @@ -3915,24 +3916,11 @@ axes.drawLabels = function(gd, ax, opts) { } } - function removeHiddenLabels() { - // Remove all hidden labels to prevent them from affecting the layout. - tickLabels.each(function(d) { - var thisLabel = d3.select(this); - var textNode = thisLabel.select('text').node(); - var opacity = window.getComputedStyle(textNode).opacity; - if (opacity == '0') { - thisLabel.select('text').text(''); - d3.select(textNode).text(''); - } - }); - } - if(ax._selections) { ax._selections[cls] = tickLabels; } - var seq = [allLabelsReady, removeHiddenLabels]; + var seq = [allLabelsReady]; // N.B. during auto-margin redraws, if the axis fixed its label overlaps // by rotating 90 degrees, do not attempt to re-fix its label overlaps From 049b7febff8639afc55c4f3da1b3cd7184f6a22a Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 13 May 2025 14:04:19 +0200 Subject: [PATCH 05/12] Fix error: d3 selection.style called as getter Also remove left-over console debug print --- src/plots/cartesian/axes.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 9d55139e45f..f879bd91851 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -3783,8 +3783,11 @@ axes.drawLabels = function(gd, ax, opts) { q > ax['_visibleLabelMin_' + anchorAx._id] ) { t.style('display', 'none'); // hidden - } else if(e.K === 'tick' && !idx && t.style('display') != 'none') { - t.style('display', null); // visible + } else if(e.K === 'tick' && !idx) { + var display = window.getComputedStyle(t.node()).display; + if (display != 'none') { + t.style('display', null); // visible + } } }); }); @@ -3807,7 +3810,6 @@ axes.drawLabels = function(gd, ax, opts) { var autoangle = null; function fixLabelOverlaps() { - console.log("fix label overlaps!"); positionLabels(tickLabels, tickAngle); // check for auto-angling if x labels overlap From 23a29f21c2a2bc0f2a0f6b3ae8d87cf5b306cfdd Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 13 May 2025 14:10:26 +0200 Subject: [PATCH 06/12] axes_test: Add precision param to new toBeCloseToArray call --- test/jasmine/tests/axes_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 4283bd8ac57..34209ff574a 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -6911,7 +6911,7 @@ describe('Test axes', function() { .filter(function(d) { return d.minor; }) .map(function(d) { return d.x; }); - expect(positions).toBeCloseToArray(expPositions); + expect(positions).toBeCloseToArray(expPositions, 3); } it('minor tickvals', function(done) { From 89677323d67f8c1635152024295382c98deb6c77 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 13 May 2025 14:24:30 +0200 Subject: [PATCH 07/12] Correct fix for "d3 selection.style called as getter" --- src/plots/cartesian/axes.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index f879bd91851..14963988be1 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -3783,11 +3783,8 @@ axes.drawLabels = function(gd, ax, opts) { q > ax['_visibleLabelMin_' + anchorAx._id] ) { t.style('display', 'none'); // hidden - } else if(e.K === 'tick' && !idx) { - var display = window.getComputedStyle(t.node()).display; - if (display != 'none') { - t.style('display', null); // visible - } + } else if(e.K === 'tick' && !idx && t.node().style.display !== 'none') { + t.style('display', null); // visible } }); }); From 2e8db5f93f8454ef78caec0be25b1fe2218f9fca Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Thu, 15 May 2025 17:02:50 +0200 Subject: [PATCH 08/12] Undo some changes done in 684d05c0 (break the CI) --- test/jasmine/tests/axes_test.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 34209ff574a..a64949b0741 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1722,13 +1722,13 @@ describe('Test axes', function() { width: 600, height: 600 }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.13, 2]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.110, 2]); return Plotly.relayout(gd, { 'xaxis.insiderange': [1, 3] }); }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.866, 3]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.889, 3]); }).then(done, done.fail); }); }); @@ -4908,32 +4908,32 @@ describe('Test axes', function() { }) .then(function() { _assert('on labels (defaults)', { - ticks: [108.75, 348, 587.25], - gridLines: [108.75, 348, 587.25], + ticks: [110.75, 350, 589.25], + gridLines: [110.75, 350, 589.25], tickLabels: [106.421, 345.671, 585.25] }); return Plotly.relayout(gd, 'xaxis.tickson', 'boundaries'); }) .then(function() { _assert('inside on boundaries', { - ticks: [228.367, 467.617], // N.B. first and last tick are clipped - gridLines: [228.367, 467.617], + ticks: [230.369, 469.619], // N.B. first and last tick are clipped + gridLines: [230.369, 469.619], tickLabels: [106.421875, 345.671875, 585.25] }); return Plotly.relayout(gd, 'xaxis.ticks', 'outside'); }) .then(function() { _assert('outside on boundaries', { - ticks: [228.367, 467.617], - gridLines: [228.367, 467.617], + ticks: [230.369, 469.619], + gridLines: [230.369, 469.619], tickLabels: [106.421875, 345.671875, 585.25] }); return Plotly.restyle(gd, 'x', [[1, 2, 1]]); }) .then(function() { _assert('fallback to *labels* on non-category axes', { - ticks: [108.75, 204.433, 300.133, 395.85, 491.533, 587.25], - gridLines: [108.75, 204.433, 300.133, 395.85, 491.533, 587.25], + ticks: [110.75, 206.449, 302.149, 397.85, 493.549, 589.25], + gridLines: [110.75, 206.449, 302.149, 397.85, 493.549, 589.25], tickLabels: [106.421, 197.121, 292.821, 388.521, 484.221, 584.921] }); }) @@ -8152,11 +8152,11 @@ describe('more react tests', function() { Plotly.newPlot(gd, fig1) .then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.134, 2]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.110, 2]); return Plotly.react(gd, fig2); }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.192, 2]); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([-0.164, 2]); }).then(done, done.fail); }); }); From b546d6136a3d674d85460e20c08cb7370e5b52ae Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Thu, 15 May 2025 17:22:36 +0200 Subject: [PATCH 09/12] Undo change to left-over failing test since 684d05c0 --- test/jasmine/tests/axes_test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index a64949b0741..6314d97a1b0 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -1697,7 +1697,7 @@ describe('Test axes', function() { return Plotly.relayout(gd, 'xaxis.autorange', true); }).then(function() { - expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.27, 3.23], 1); + expect(gd._fullLayout.xaxis.range).toBeCloseToArray([0.37, 3.22], 1); }) .then(done, done.fail); }); From 846c0ab5fd8c09b9eb21f149a240ab6e3ba49f95 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 20 May 2025 15:22:22 +0200 Subject: [PATCH 10/12] Try fixing failed baseline test container-colorbar-vertical-w-margin - in calculatelabelLevelBbox bbox measurement for hidden labels was broken, because of display none - display 'none' led to repeated calls of adjustTicklabelOverflow that set display to null, then to none, then to null... --- src/plots/cartesian/axes.js | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 14963988be1..5ca9c97e65b 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -2946,8 +2946,10 @@ function calcLabelLevelBbox(ax, cls, mainLinePositionShift) { bottom = -Infinity; left = Infinity; right = -Infinity; + var xAxis = ax._id.charAt(0) === 'x'; ax._selections[cls].each(function() { var thisLabel = selectTickLabel(this); + var hidden = thisLabel.style('display') === 'none'; // Use parent node , to make Drawing.bBox // retrieve a bbox computed with transform info // @@ -2955,11 +2957,31 @@ function calcLabelLevelBbox(ax, cls, mainLinePositionShift) { // (like in fixLabelOverlaps) instead and use Axes.getPxPosition // together with the makeLabelFns outputs and `tickangle` // to compute one bbox per (tick value x tick style) + if (hidden) { + // turn on label display temporarily to calculate its bbox + thisLabel.style('display', null); + } var bb = Drawing.bBox(thisLabel.node().parentNode); - top = Math.min(top, bb.top); - bottom = Math.max(bottom, bb.bottom); - left = Math.min(left, bb.left); - right = Math.max(right, bb.right); + if (hidden) { + selectTickLabel(this).style('display', 'none'); + } + var currentTop = bb.top; + var currentBottom = bb.bottom; + var currentLeft = bb.left; + var currentRight = bb.right; + if (hidden) { + if (xAxis) { + currentTop = top; + currentBottom = bottom; + } else { + currentLeft = left; + currentRight = right; + } + } + top = Math.min(top, currentTop); + bottom = Math.max(bottom, currentBottom); + left = Math.min(left, currentLeft); + right = Math.max(right, currentRight); }); } else { var dummyCalc = axes.makeLabelFns(ax, mainLinePositionShift); @@ -3707,8 +3729,8 @@ axes.drawLabels = function(gd, ax, opts) { var t = thisLabel.select('text'); if(adjust) { if(hideOverflow) t.style('display', 'none'); // hidden - } else { - t.style('display', null); // visible + } else if(t.node().style.display !== 'none'){ + t.style('display', null); if(side === 'bottom' || side === 'right') { visibleLabelMin = Math.min(visibleLabelMin, isX ? bb.top : bb.left); From 65fed4a8385e24ea46c5c9ba1fc77c7285ca7f08 Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Tue, 20 May 2025 15:50:16 +0200 Subject: [PATCH 11/12] baseline image for zz-label-spacing --- test/image/baselines/zz-label-spacing.png | Bin 0 -> 29015 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 test/image/baselines/zz-label-spacing.png diff --git a/test/image/baselines/zz-label-spacing.png b/test/image/baselines/zz-label-spacing.png new file mode 100644 index 0000000000000000000000000000000000000000..1d561dd408b27c3ca899709485242bd0455d93ff GIT binary patch literal 29015 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

*X?qGb67`#oa|8O};wqfUYsrU8X{A!9(IjC7r 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%0DPlAGeSJx8JY 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�u4gDHel91kU3F7#!CS!bg3>tkEpQ$>oiH` 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 R;Dd=|nrgbLStqf${{bns4nP0^ literal 0 HcmV?d00001 From a0affddf2d3eac7c7767807a391a00abb984f87c Mon Sep 17 00:00:00 2001 From: My-Tien Nguyen Date: Thu, 22 May 2025 16:19:21 +0200 Subject: [PATCH 12/12] Try fixing automargin behavior when setting display: 'none' for hidden labels This is a second attempt after 846c0ab5 in which I tried to restore the previous behavior of calcLabelLevelBbox. I now think the hidden label should not contribute to the resulting bbox at all, because it's hidden. This will break baseline tests but should be the correct behavior. --- src/plots/cartesian/axes.js | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/src/plots/cartesian/axes.js b/src/plots/cartesian/axes.js index 5ca9c97e65b..ccf1cb5fa8b 100644 --- a/src/plots/cartesian/axes.js +++ b/src/plots/cartesian/axes.js @@ -2946,10 +2946,8 @@ function calcLabelLevelBbox(ax, cls, mainLinePositionShift) { bottom = -Infinity; left = Infinity; right = -Infinity; - var xAxis = ax._id.charAt(0) === 'x'; ax._selections[cls].each(function() { var thisLabel = selectTickLabel(this); - var hidden = thisLabel.style('display') === 'none'; // Use parent node , to make Drawing.bBox // retrieve a bbox computed with transform info // @@ -2957,31 +2955,13 @@ function calcLabelLevelBbox(ax, cls, mainLinePositionShift) { // (like in fixLabelOverlaps) instead and use Axes.getPxPosition // together with the makeLabelFns outputs and `tickangle` // to compute one bbox per (tick value x tick style) - if (hidden) { - // turn on label display temporarily to calculate its bbox - thisLabel.style('display', null); + if (thisLabel.style('display') !== 'none') { + var bb = Drawing.bBox(thisLabel.node().parentNode); + top = Math.min(top, bb.top); + bottom = Math.max(bottom, bb.bottom); + left = Math.min(left, bb.left); + right = Math.max(right, bb.right); } - var bb = Drawing.bBox(thisLabel.node().parentNode); - if (hidden) { - selectTickLabel(this).style('display', 'none'); - } - var currentTop = bb.top; - var currentBottom = bb.bottom; - var currentLeft = bb.left; - var currentRight = bb.right; - if (hidden) { - if (xAxis) { - currentTop = top; - currentBottom = bottom; - } else { - currentLeft = left; - currentRight = right; - } - } - top = Math.min(top, currentTop); - bottom = Math.max(bottom, currentBottom); - left = Math.min(left, currentLeft); - right = Math.max(right, currentRight); }); } else { var dummyCalc = axes.makeLabelFns(ax, mainLinePositionShift);