diff --git a/src/plots/plots.js b/src/plots/plots.js index c28b8f3df72..34646cb5668 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1864,6 +1864,9 @@ function initMargins(fullLayout) { if(!fullLayout._pushmarginIds) fullLayout._pushmarginIds = {}; } +var minFinalWidth = 64; // could possibly be exposed as layout.margin.minfinalwidth +var minFinalHeight = 64; // could possibly be exposed as layout.margin.minfinalheight + /** * autoMargin: called by components that may need to expand the margins to * be rendered on-plot. @@ -1881,6 +1884,10 @@ function initMargins(fullLayout) { */ plots.autoMargin = function(gd, id, o) { var fullLayout = gd._fullLayout; + var width = fullLayout.width; + var height = fullLayout.height; + var maxSpaceW = Math.max(0, width - minFinalWidth); + var maxSpaceH = Math.max(0, height - minFinalHeight); var pushMargin = fullLayout._pushmargin; var pushMarginIds = fullLayout._pushmarginIds; @@ -1900,13 +1907,15 @@ plots.autoMargin = function(gd, id, o) { // if the item is too big, just give it enough automargin to // make sure you can still grab it and bring it back - if(o.l + o.r > fullLayout.width * 0.5) { - Lib.log('Margin push', id, 'is too big in x, dropping'); - o.l = o.r = 0; + var rW = (o.l + o.r) / maxSpaceW; + if(rW > 1) { + o.l /= rW; + o.r /= rW; } - if(o.b + o.t > fullLayout.height * 0.5) { - Lib.log('Margin push', id, 'is too big in y, dropping'); - o.b = o.t = 0; + var rH = (o.t + o.b) / maxSpaceH; + if(rH > 1) { + o.t /= rH; + o.b /= rH; } var xl = o.xl !== undefined ? o.xl : o.x; @@ -1931,6 +1940,11 @@ plots.autoMargin = function(gd, id, o) { plots.doAutoMargin = function(gd) { var fullLayout = gd._fullLayout; + var width = fullLayout.width; + var height = fullLayout.height; + var maxSpaceW = Math.max(0, width - minFinalWidth); + var maxSpaceH = Math.max(0, height - minFinalHeight); + if(!fullLayout._size) fullLayout._size = {}; initMargins(fullLayout); @@ -1945,8 +1959,6 @@ plots.doAutoMargin = function(gd) { var mr = margin.r; var mt = margin.t; var mb = margin.b; - var width = fullLayout.width; - var height = fullLayout.height; var pushMargin = fullLayout._pushmargin; var pushMarginIds = fullLayout._pushmarginIds; @@ -1978,11 +1990,10 @@ plots.doAutoMargin = function(gd) { if(isNumeric(pl) && pushMargin[k2].r) { var fr = pushMargin[k2].r.val; var pr = pushMargin[k2].r.size; - if(fr > fl) { var newL = (pl * fr + (pr - width) * fl) / (fr - fl); var newR = (pr * (1 - fl) + (pl - width) * (1 - fr)) / (fr - fl); - if(newL >= 0 && newR >= 0 && width - (newL + newR) > 0 && newL + newR > ml + mr) { + if(newL + newR > ml + mr) { ml = newL; mr = newR; } @@ -1992,11 +2003,10 @@ plots.doAutoMargin = function(gd) { if(isNumeric(pb) && pushMargin[k2].t) { var ft = pushMargin[k2].t.val; var pt = pushMargin[k2].t.size; - if(ft > fb) { var newB = (pb * ft + (pt - height) * fb) / (ft - fb); var newT = (pt * (1 - fb) + (pb - height) * (1 - ft)) / (ft - fb); - if(newB >= 0 && newT >= 0 && height - (newT + newB) > 0 && newB + newT > mb + mt) { + if(newB + newT > mb + mt) { mb = newB; mt = newT; } @@ -2006,6 +2016,18 @@ plots.doAutoMargin = function(gd) { } } + var rW = (ml + mr) / maxSpaceW; + if(rW > 1) { + ml /= rW; + mr /= rW; + } + + var rH = (mb + mt) / maxSpaceH; + if(rH > 1) { + mb /= rH; + mt /= rH; + } + gs.l = Math.round(ml); gs.r = Math.round(mr); gs.t = Math.round(mt); diff --git a/test/image/baselines/automargin-large-margins-both-sides.png b/test/image/baselines/automargin-large-margins-both-sides.png new file mode 100644 index 00000000000..fc17d8fe808 Binary files /dev/null and b/test/image/baselines/automargin-large-margins-both-sides.png differ diff --git a/test/image/baselines/automargin-large-margins-horizontal.png b/test/image/baselines/automargin-large-margins-horizontal.png new file mode 100644 index 00000000000..2641dd8d97e Binary files /dev/null and b/test/image/baselines/automargin-large-margins-horizontal.png differ diff --git a/test/image/baselines/automargin-large-margins.png b/test/image/baselines/automargin-large-margins.png new file mode 100644 index 00000000000..dad69bba747 Binary files /dev/null and b/test/image/baselines/automargin-large-margins.png differ diff --git a/test/image/baselines/legend_small_horizontal.png b/test/image/baselines/legend_small_horizontal.png index 97445e02ebe..925f8396be2 100644 Binary files a/test/image/baselines/legend_small_horizontal.png and b/test/image/baselines/legend_small_horizontal.png differ diff --git a/test/image/mocks/automargin-large-margins-both-sides.json b/test/image/mocks/automargin-large-margins-both-sides.json new file mode 100644 index 00000000000..66c741b0bea --- /dev/null +++ b/test/image/mocks/automargin-large-margins-both-sides.json @@ -0,0 +1,54 @@ +{ + "data": [{ + "name": "< D E A T H >", + "marker": { "color": "red" }, + "y": [ + "Antonio Vivaldi", + "Johann Sebastian Bach", + "Wolfgang Amadeus Mozart", + "Ludwig van Beethoven" + ], + "x": [ + "1741", + "1750", + "1791", + "1827" + ] + }, + { + "name": "< B I R T H >", + "marker": { "color": "blue" }, + "y": [ + "Antonio Vivaldi", + "Johann Sebastian Bach", + "Wolfgang Amadeus Mozart", + "Ludwig van Beethoven" + ], + "x": [ + "1678", + "1685", + "1756", + "1770" + ] + }], + "layout": { + "title": { + "text": "Longest and shortest
names and time periods" + }, + "width": 200, + "height": 200, + "margin": { + "t": 80, + "b": 20, + "l": 20, + "r": 20 + }, + "xaxis": { + "type": "date", + "automargin": true + }, + "yaxis": { + "automargin": true + } + } +} diff --git a/test/image/mocks/automargin-large-margins-horizontal.json b/test/image/mocks/automargin-large-margins-horizontal.json new file mode 100644 index 00000000000..931e87a4731 --- /dev/null +++ b/test/image/mocks/automargin-large-margins-horizontal.json @@ -0,0 +1,55 @@ +{ + "data": [{ + "name": "< D E A T H >", + "marker": { "color": "red" }, + "y": [ + "Antonio Vivaldi", + "Johann Sebastian Bach", + "Wolfgang Amadeus Mozart", + "Ludwig van Beethoven" + ], + "x": [ + "1741", + "1750", + "1791", + "1827" + ] + }, + { + "name": "< B I R T H >", + "marker": { "color": "blue" }, + "y": [ + "Antonio Vivaldi", + "Johann Sebastian Bach", + "Wolfgang Amadeus Mozart", + "Ludwig van Beethoven" + ], + "x": [ + "1678", + "1685", + "1756", + "1770" + ] + }], + "layout": { + "showlegend": false, + "title": { + "text": "Longest and shortest
names and time periods" + }, + "width": 240, + "height": 200, + "margin": { + "t": 80, + "b": 20, + "l": 20, + "r": 20 + }, + "xaxis": { + "type": "date", + "automargin": true + }, + "yaxis": { + "automargin": true + } + } +} diff --git a/test/image/mocks/automargin-large-margins.json b/test/image/mocks/automargin-large-margins.json new file mode 100644 index 00000000000..589ba2a2213 --- /dev/null +++ b/test/image/mocks/automargin-large-margins.json @@ -0,0 +1,54 @@ +{ + "data": [{ + "name": "< D E A T H >", + "marker": { "color": "red" }, + "x": [ + "Antonio Vivaldi", + "Johann Sebastian Bach", + "Wolfgang Amadeus Mozart", + "Ludwig van Beethoven" + ], + "y": [ + "1741", + "1750", + "1791", + "1827" + ] + }, + { + "name": "< B I R T H >", + "marker": { "color": "blue" }, + "x": [ + "Antonio Vivaldi", + "Johann Sebastian Bach", + "Wolfgang Amadeus Mozart", + "Ludwig van Beethoven" + ], + "y": [ + "1678", + "1685", + "1756", + "1770" + ] + }], + "layout": { + "title": { + "text": "Longest and shortest
names and time periods" + }, + "width": 240, + "height": 300, + "margin": { + "t": 80, + "b": 20, + "l": 20, + "r": 20 + }, + "yaxis": { + "type": "date", + "automargin": true + }, + "xaxis": { + "automargin": true + } + } +} diff --git a/test/jasmine/tests/axes_test.js b/test/jasmine/tests/axes_test.js index 7a135ba11c0..c6f864dda9b 100644 --- a/test/jasmine/tests/axes_test.js +++ b/test/jasmine/tests/axes_test.js @@ -3856,7 +3856,7 @@ describe('Test axes', function() { .then(function() { return Plotly.relayout(gd, 'height', 100); }) .then(function() { _assert('after relayout to *small* height', { - bottomLowerBound: 30, + bottomLowerBound: 15, totalHeight: 100 }); }) @@ -3896,7 +3896,7 @@ describe('Test axes', function() { .then(function() { return Plotly.relayout(gd, 'width', 100); }) .then(function() { _assert('after relayout to *small* width', { - leftLowerBound: 30, + leftLowerBound: 15, totalWidth: 100 }); }) diff --git a/test/jasmine/tests/indicator_test.js b/test/jasmine/tests/indicator_test.js index 4bc28714830..69f247d31b5 100644 --- a/test/jasmine/tests/indicator_test.js +++ b/test/jasmine/tests/indicator_test.js @@ -171,7 +171,7 @@ describe('Indicator plot', function() { return Plotly.relayout(gd, {width: 200, height: 200}); }) .then(function() { - checkNumbersScale(0.2, 'should scale down'); + checkNumbersScale(0.4794007490636704, 'should scale down'); return Plotly.relayout(gd, {width: 400, height: 400}); }) .then(function() { diff --git a/test/jasmine/tests/legend_scroll_test.js b/test/jasmine/tests/legend_scroll_test.js index 3ae4942c6f0..e1e31f7c3e7 100644 --- a/test/jasmine/tests/legend_scroll_test.js +++ b/test/jasmine/tests/legend_scroll_test.js @@ -405,7 +405,7 @@ describe('The legend', function() { expect(countLegendClipPaths(gd)).toBe(1); // clippath resized to new height less than new plot height - expect(+legendHeight).toBe(getPlotHeight(gd)); + expect(+legendHeight).toBeGreaterThan(getPlotHeight(gd)); expect(+legendHeight).toBeLessThan(+origLegendHeight); done(); diff --git a/test/jasmine/tests/mock_test.js b/test/jasmine/tests/mock_test.js index 86825fc7e0d..833407c8596 100644 --- a/test/jasmine/tests/mock_test.js +++ b/test/jasmine/tests/mock_test.js @@ -39,6 +39,9 @@ var list = [ 'annotations', 'annotations-autorange', 'arrow-markers', + 'automargin-large-margins', + 'automargin-large-margins-both-sides', + 'automargin-large-margins-horizontal', 'automargin-mirror-all', 'automargin-mirror-allticks', 'automargin-multiline-titles', @@ -1103,6 +1106,9 @@ figs['animation_bar'] = require('@mocks/animation_bar'); // figs['annotations'] = require('@mocks/annotations'); // figs['annotations-autorange'] = require('@mocks/annotations-autorange'); figs['arrow-markers'] = require('@mocks/arrow-markers'); +figs['automargin-large-margins'] = require('@mocks/automargin-large-margins'); +figs['automargin-large-margins-both-sides'] = require('@mocks/automargin-large-margins-both-sides'); +figs['automargin-large-margins-horizontal'] = require('@mocks/automargin-large-margins-horizontal'); figs['automargin-mirror-all'] = require('@mocks/automargin-mirror-all'); figs['automargin-mirror-allticks'] = require('@mocks/automargin-mirror-allticks'); figs['automargin-multiline-titles'] = require('@mocks/automargin-multiline-titles');