Skip to content

Commit e01cb00

Browse files
authored
Merge pull request #635 from plotly/autosize-refactor
Refactor plot autosize
2 parents 35bbb86 + 5fb7cd1 commit e01cb00

File tree

12 files changed

+427
-130
lines changed

12 files changed

+427
-130
lines changed

src/lib/index.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,9 @@ lib.getPlotDiv = function(el) {
394394

395395
lib.isPlotDiv = function(el) {
396396
var el3 = d3.select(el);
397-
return el3.size() && el3.classed('js-plotly-plot');
397+
return el3.node() instanceof HTMLElement &&
398+
el3.size() &&
399+
el3.classed('js-plotly-plot');
398400
};
399401

400402
lib.removeElement = function(el) {

src/plot_api/plot_api.js

+22-103
Original file line numberDiff line numberDiff line change
@@ -422,10 +422,6 @@ function plotPolar(gd, data, layout) {
422422
if(layout) gd.layout = layout;
423423
Polar.manager.fillLayout(gd);
424424

425-
if(gd._fullLayout.autosize === 'initial' && gd._context.autosizable) {
426-
plotAutoSize(gd, {});
427-
gd._fullLayout.autosize = layout.autosize = true;
428-
}
429425
// resize canvas
430426
paperDiv.style({
431427
width: gd._fullLayout.width + 'px',
@@ -1778,8 +1774,6 @@ function _relayout(gd, aobj) {
17781774
var redoit = {},
17791775
undoit = {};
17801776

1781-
var hw = ['height', 'width'];
1782-
17831777
// for attrs that interact (like scales & autoscales), save the
17841778
// old vals before making the change
17851779
// val=undefined will not set a value, just record what the value was.
@@ -1827,13 +1821,14 @@ function _relayout(gd, aobj) {
18271821
// op and has no flag.
18281822
undoit[ai] = (pleaf === 'reverse') ? vi : p.get();
18291823

1830-
// check autosize or autorange vs size and range
1831-
if(hw.indexOf(ai) !== -1) {
1832-
doextra('autosize', false);
1833-
}
1834-
else if(ai === 'autosize') {
1835-
doextra(hw, undefined);
1824+
// Setting width or height to null must reset the graph's width / height
1825+
// back to its initial value as computed during the first pass in Plots.plotAutoSize.
1826+
//
1827+
// To do so, we must manually set them back here using the _initialAutoSize cache.
1828+
if(['width', 'height'].indexOf(ai) !== -1 && vi === null) {
1829+
gd._fullLayout[ai] = gd._initialAutoSize[ai];
18361830
}
1831+
// check autorange vs range
18371832
else if(pleafPlus.match(/^[xyz]axis[0-9]*\.range(\[[0|1]\])?$/)) {
18381833
doextra(ptrunk + '.autorange', false);
18391834
}
@@ -2017,10 +2012,21 @@ function _relayout(gd, aobj) {
20172012
}
20182013
}
20192014

2020-
// calculate autosizing - if size hasn't changed,
2021-
// will remove h&w so we don't need to redraw
2022-
if(aobj.autosize) aobj = plotAutoSize(gd, aobj);
2023-
if(aobj.height || aobj.width || aobj.autosize) flags.docalc = true;
2015+
var oldWidth = gd._fullLayout.width,
2016+
oldHeight = gd._fullLayout.height;
2017+
2018+
// coerce the updated layout
2019+
Plots.supplyDefaults(gd);
2020+
2021+
// calculate autosizing
2022+
if(gd.layout.autosize) Plots.plotAutoSize(gd, gd.layout, gd._fullLayout);
2023+
2024+
// avoid unnecessary redraws
2025+
var hasSizechanged = aobj.height || aobj.width ||
2026+
(gd._fullLayout.width !== oldWidth) ||
2027+
(gd._fullLayout.height !== oldHeight);
2028+
2029+
if(hasSizechanged) flags.docalc = true;
20242030

20252031
if(flags.doplot || flags.docalc) {
20262032
flags.layoutReplot = true;
@@ -2651,86 +2657,6 @@ Plotly.purge = function purge(gd) {
26512657
return gd;
26522658
};
26532659

2654-
/**
2655-
* Reduce all reserved margin objects to a single required margin reservation.
2656-
*
2657-
* @param {Object} margins
2658-
* @returns {{left: number, right: number, bottom: number, top: number}}
2659-
*/
2660-
function calculateReservedMargins(margins) {
2661-
var resultingMargin = {left: 0, right: 0, bottom: 0, top: 0},
2662-
marginName;
2663-
2664-
if(margins) {
2665-
for(marginName in margins) {
2666-
if(margins.hasOwnProperty(marginName)) {
2667-
resultingMargin.left += margins[marginName].left || 0;
2668-
resultingMargin.right += margins[marginName].right || 0;
2669-
resultingMargin.bottom += margins[marginName].bottom || 0;
2670-
resultingMargin.top += margins[marginName].top || 0;
2671-
}
2672-
}
2673-
}
2674-
return resultingMargin;
2675-
}
2676-
2677-
function plotAutoSize(gd, aobj) {
2678-
var fullLayout = gd._fullLayout,
2679-
context = gd._context,
2680-
computedStyle;
2681-
2682-
var newHeight, newWidth;
2683-
2684-
gd.emit('plotly_autosize');
2685-
2686-
// embedded in an iframe - just take the full iframe size
2687-
// if we get to this point, with no aspect ratio restrictions
2688-
if(gd._context.fillFrame) {
2689-
newWidth = window.innerWidth;
2690-
newHeight = window.innerHeight;
2691-
2692-
// somehow we get a few extra px height sometimes...
2693-
// just hide it
2694-
document.body.style.overflow = 'hidden';
2695-
}
2696-
else if(isNumeric(context.frameMargins) && context.frameMargins > 0) {
2697-
var reservedMargins = calculateReservedMargins(gd._boundingBoxMargins),
2698-
reservedWidth = reservedMargins.left + reservedMargins.right,
2699-
reservedHeight = reservedMargins.bottom + reservedMargins.top,
2700-
gdBB = fullLayout._container.node().getBoundingClientRect(),
2701-
factor = 1 - 2 * context.frameMargins;
2702-
2703-
newWidth = Math.round(factor * (gdBB.width - reservedWidth));
2704-
newHeight = Math.round(factor * (gdBB.height - reservedHeight));
2705-
}
2706-
else {
2707-
// plotly.js - let the developers do what they want, either
2708-
// provide height and width for the container div,
2709-
// specify size in layout, or take the defaults,
2710-
// but don't enforce any ratio restrictions
2711-
computedStyle = window.getComputedStyle(gd);
2712-
newHeight = parseFloat(computedStyle.height) || fullLayout.height;
2713-
newWidth = parseFloat(computedStyle.width) || fullLayout.width;
2714-
}
2715-
2716-
if(Math.abs(fullLayout.width - newWidth) > 1 ||
2717-
Math.abs(fullLayout.height - newHeight) > 1) {
2718-
fullLayout.height = gd.layout.height = newHeight;
2719-
fullLayout.width = gd.layout.width = newWidth;
2720-
}
2721-
// if there's no size change, update layout but
2722-
// delete the autosize attr so we don't redraw
2723-
// but can't call layoutStyles for initial autosize
2724-
else if(fullLayout.autosize !== 'initial') {
2725-
delete(aobj.autosize);
2726-
fullLayout.autosize = gd.layout.autosize = true;
2727-
}
2728-
2729-
Plots.sanitizeMargins(fullLayout);
2730-
2731-
return aobj;
2732-
}
2733-
27342660
// -------------------------------------------------------
27352661
// makePlotFramework: Create the plot container and axes
27362662
// -------------------------------------------------------
@@ -2750,13 +2676,6 @@ function makePlotFramework(gd) {
27502676
.classed('svg-container', true)
27512677
.style('position', 'relative');
27522678

2753-
// Initial autosize
2754-
if(fullLayout.autosize === 'initial') {
2755-
plotAutoSize(gd, {});
2756-
fullLayout.autosize = true;
2757-
gd.layout.autosize = true;
2758-
}
2759-
27602679
// Make the graph containers
27612680
// start fresh each time we get here, so we know the order comes out
27622681
// right, rather than enter/exit which can muck up the order

src/plot_api/plot_config.js

+4-3
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,13 @@ module.exports = {
2626
// we can edit titles, move annotations, etc
2727
editable: false,
2828

29+
// DO autosize once regardless of layout.autosize
30+
// (use default width or height values otherwise)
31+
autosizable: false,
32+
2933
// set the length of the undo/redo queue
3034
queueLength: 0,
3135

32-
// plot will respect layout.autosize=true and infer its container size
33-
autosizable: false,
34-
3536
// if we DO autosize, do we fill the container or the screen?
3637
fillFrame: false,
3738

src/plots/layout_attributes.js

+9-5
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,17 @@ module.exports = {
4343
description: 'Sets the title font.'
4444
}),
4545
autosize: {
46-
valType: 'enumerated',
46+
valType: 'boolean',
4747
role: 'info',
48-
// TODO: better handling of 'initial'
49-
values: [true, false, 'initial'],
48+
dflt: false,
5049
description: [
51-
'Determines whether or not the dimensions of the figure are',
52-
'computed as a function of the display size.'
50+
'Determines whether or not a layout width or height',
51+
'that has been left undefined by the user',
52+
'is initialized on each relayout.',
53+
54+
'Note that, regardless of this attribute,',
55+
'an undefined layout width or height',
56+
'is always initialized on the first call to plot.'
5357
].join(' ')
5458
},
5559
width: {

0 commit comments

Comments
 (0)