diff --git a/draftlogs/6307_add.md b/draftlogs/6307_add.md new file mode 100644 index 00000000000..f3240a3a6a7 --- /dev/null +++ b/draftlogs/6307_add.md @@ -0,0 +1 @@ +Add `minreducedwidth` and `minreducedheight` as layout parameters [[#6307](https://github.com/plotly/plotly.js/pull/6307)] \ No newline at end of file diff --git a/src/plots/layout_attributes.js b/src/plots/layout_attributes.js index cc6e4d973a5..38fe31ed189 100644 --- a/src/plots/layout_attributes.js +++ b/src/plots/layout_attributes.js @@ -189,6 +189,20 @@ module.exports = { 'Sets the plot\'s height (in px).' ].join(' ') }, + minreducedwidth: { + valType: 'number', + min: 2, + dflt: 64, + editType: 'plot', + description: 'Minimum width of the plot with margin.automargin applied (in px)' + }, + minreducedheight: { + valType: 'number', + min: 2, + dflt: 64, + editType: 'plot', + description: 'Minimum height of the plot with margin.automargin applied (in px)' + }, margin: { l: { valType: 'number', diff --git a/src/plots/plots.js b/src/plots/plots.js index e7018f70647..7b28bc9b543 100644 --- a/src/plots/plots.js +++ b/src/plots/plots.js @@ -1506,6 +1506,9 @@ plots.supplyLayoutGlobalDefaults = function(layoutIn, layoutOut, formatObj) { coerce('width'); coerce('height'); + coerce('minreducedwidth'); + coerce('minreducedheight'); + coerce('margin.l'); coerce('margin.r'); coerce('margin.t'); @@ -1861,10 +1864,6 @@ function initMargins(fullLayout) { var MIN_SPECIFIED_WIDTH = 2; var MIN_SPECIFIED_HEIGHT = 2; -// could be exposed as an option - the smallest we will allow automargin to shrink a larger plot -var MIN_REDUCED_WIDTH = 64; -var MIN_REDUCED_HEIGHT = 64; - /** * autoMargin: called by components that may need to expand the margins to * be rendered on-plot. @@ -1885,17 +1884,19 @@ plots.autoMargin = function(gd, id, o) { var width = fullLayout.width; var height = fullLayout.height; var margin = fullLayout.margin; + var minreducedwidth = fullLayout.minreducedwidth; + var minreducedheight = fullLayout.minreducedheight; var minFinalWidth = Lib.constrain( width - margin.l - margin.r, MIN_SPECIFIED_WIDTH, - MIN_REDUCED_WIDTH + minreducedwidth ); var minFinalHeight = Lib.constrain( height - margin.t - margin.b, MIN_SPECIFIED_HEIGHT, - MIN_REDUCED_HEIGHT + minreducedheight ); var maxSpaceW = Math.max(0, width - minFinalWidth); @@ -1974,6 +1975,8 @@ plots.doAutoMargin = function(gd) { var mb = margin.b; var pushMargin = fullLayout._pushmargin; var pushMarginIds = fullLayout._pushmarginIds; + var minreducedwidth = fullLayout.minreducedwidth; + var minreducedheight = fullLayout.minreducedheight; if(fullLayout.margin.autoexpand !== false) { for(var k in pushMargin) { @@ -2032,13 +2035,13 @@ plots.doAutoMargin = function(gd) { var minFinalWidth = Lib.constrain( width - margin.l - margin.r, MIN_SPECIFIED_WIDTH, - MIN_REDUCED_WIDTH + minreducedwidth ); var minFinalHeight = Lib.constrain( height - margin.t - margin.b, MIN_SPECIFIED_HEIGHT, - MIN_REDUCED_HEIGHT + minreducedheight ); var maxSpaceW = Math.max(0, width - minFinalWidth); diff --git a/test/image/baselines/z-automargin-minreducedheight.png b/test/image/baselines/z-automargin-minreducedheight.png new file mode 100644 index 00000000000..af407e59e68 Binary files /dev/null and b/test/image/baselines/z-automargin-minreducedheight.png differ diff --git a/test/image/baselines/z-automargin-minreducedwidth.png b/test/image/baselines/z-automargin-minreducedwidth.png new file mode 100644 index 00000000000..a4ea346f052 Binary files /dev/null and b/test/image/baselines/z-automargin-minreducedwidth.png differ diff --git a/test/image/mocks/z-automargin-minreducedheight.json b/test/image/mocks/z-automargin-minreducedheight.json new file mode 100644 index 00000000000..7e48b8085f4 --- /dev/null +++ b/test/image/mocks/z-automargin-minreducedheight.json @@ -0,0 +1,55 @@ +{ + "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, + "minreducedheight": 55, + "margin": { + "t": 80, + "b": 20, + "l": 20, + "r": 20 + }, + "yaxis": { + "type": "date", + "automargin": true + }, + "xaxis": { + "automargin": true + } + } +} diff --git a/test/image/mocks/z-automargin-minreducedwidth.json b/test/image/mocks/z-automargin-minreducedwidth.json new file mode 100644 index 00000000000..56ce67a9de4 --- /dev/null +++ b/test/image/mocks/z-automargin-minreducedwidth.json @@ -0,0 +1,56 @@ +{ + "data": [{ + "name": "< D E A T H >", + "marker": { "color": "red" }, + "y": [ + "A n t o n i o V i v a l d i", + "J o h a n n S e b a s t i a n B a c h", + "W o l f g a n g A m a d e u s M o z a r t", + "L u d w i g v a n B e e t h o v e n" + ], + "x": [ + "1741", + "1750", + "1791", + "1827" + ] + }, + { + "name": "< B I R T H >", + "marker": { "color": "blue" }, + "y": [ + "A n t o n i o V i v a l d i", + "J o h a n n S e b a s t i a n B a c h", + "W o l f g a n g A m a d e u s M o z a r t", + "L u d w i g v a n B e e t h o v e n" + ], + "x": [ + "1678", + "1685", + "1756", + "1770" + ] + }], + "layout": { + "showlegend": false, + "title": { + "text": "Longest and shortest
names and time periods" + }, + "width": 240, + "height": 200, + "minreducedwidth": 55, + "margin": { + "t": 80, + "b": 20, + "l": 20, + "r": 20 + }, + "xaxis": { + "type": "date", + "automargin": true + }, + "yaxis": { + "automargin": true + } + } +} diff --git a/test/jasmine/tests/plots_test.js b/test/jasmine/tests/plots_test.js index 3191ff11d2c..13c5fa6b941 100644 --- a/test/jasmine/tests/plots_test.js +++ b/test/jasmine/tests/plots_test.js @@ -1326,3 +1326,46 @@ describe('grids', function() { .then(done, done.fail); }); }); + +describe('Test Plots with automargin and minreducedwidth/height', function() { + var gd; + + beforeEach(function() { + gd = createGraphDiv(); + }); + + afterEach(destroyGraphDiv); + + it('should resize the plot area when tweaking min-reduced width & height', function(done) { + function assert(attr, exp) { + var xy = d3Select('rect.nsewdrag')[0][0]; + expect(xy.getAttribute(attr)).toEqual(exp); + } + + function assertClose(attr, exp) { + var xy = d3Select('rect.nsewdrag')[0][0]; + expect(xy.getAttribute(attr)).toBeCloseTo(exp, -1); + } + + var fig = require('@mocks/z-automargin-minreducedheight.json'); + + Plotly.newPlot(gd, fig) + .then(function() { + assertClose('height', '55'); + }) + .then(function() { + return Plotly.relayout(gd, 'minreducedheight', 100); + }) + .then(function() { + assert('height', '100'); + }) + .then(function() { + return Plotly.relayout(gd, 'minreducedwidth', 100); + }) + .then(function() { + assert('width', '100'); + assert('height', '100'); + }) + .then(done, done.fail); + }); +}); diff --git a/test/plot-schema.json b/test/plot-schema.json index 7b882a3ea25..29bcfafc16e 100644 --- a/test/plot-schema.json +++ b/test/plot-schema.json @@ -3386,6 +3386,20 @@ "editType": "none", "valType": "string" }, + "minreducedheight": { + "description": "Minimum height of the plot with margin.automargin applied (in px)", + "dflt": 64, + "editType": "plot", + "min": 2, + "valType": "number" + }, + "minreducedwidth": { + "description": "Minimum width of the plot with margin.automargin applied (in px)", + "dflt": 64, + "editType": "plot", + "min": 2, + "valType": "number" + }, "modebar": { "activecolor": { "description": "Sets the color of the active or hovered on icons in the modebar.",