Skip to content

Commit 636a356

Browse files
authored
Merge pull request #3746 from plotly/toimage-current-graph-width-height
Add way for `toImage` to export images with current graph width/height
2 parents adf7ca2 + 6bff217 commit 636a356

File tree

5 files changed

+65
-20
lines changed

5 files changed

+65
-20
lines changed

src/components/modebar/buttons.js

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

1211
var Registry = require('../../registry');
@@ -44,7 +43,6 @@ var modeBarButtons = module.exports = {};
4443
* @param {boolean} [toggle]
4544
* is the button a toggle button?
4645
*/
47-
4846
modeBarButtons.toImage = {
4947
name: 'toImage',
5048
title: function(gd) {
@@ -67,7 +65,7 @@ modeBarButtons.toImage = {
6765
}
6866

6967
['filename', 'width', 'height', 'scale'].forEach(function(key) {
70-
if(toImageButtonOptions[key]) {
68+
if(key in toImageButtonOptions) {
7169
opts[key] = toImageButtonOptions[key];
7270
}
7371
});

src/plot_api/to_image.js

+21-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
'use strict';
1010

11+
var isNumeric = require('fast-isnumeric');
12+
1113
var plotApi = require('./plot_api');
1214
var Lib = require('../lib');
1315

@@ -27,15 +29,17 @@ var attrs = {
2729
min: 1,
2830
description: [
2931
'Sets the exported image width.',
30-
'Defaults to the value found in `layout.width`'
32+
'Defaults to the value found in `layout.width`',
33+
'If set to *null*, the exported image width will match the current graph width.'
3134
].join(' ')
3235
},
3336
height: {
3437
valType: 'number',
3538
min: 1,
3639
description: [
3740
'Sets the exported image height.',
38-
'Defaults to the value found in `layout.height`'
41+
'Defaults to the value found in `layout.height`',
42+
'If set to *null*, the exported image height will match the current graph height.'
3943
].join(' ')
4044
},
4145
scale: {
@@ -87,23 +91,27 @@ function toImage(gd, opts) {
8791
var data;
8892
var layout;
8993
var config;
94+
var fullLayout;
9095

9196
if(Lib.isPlainObject(gd)) {
9297
data = gd.data || [];
9398
layout = gd.layout || {};
9499
config = gd.config || {};
100+
fullLayout = {};
95101
} else {
96102
gd = Lib.getGraphDiv(gd);
97103
data = Lib.extendDeep([], gd.data);
98104
layout = Lib.extendDeep({}, gd.layout);
99105
config = gd._context;
106+
fullLayout = gd._fullLayout || {};
100107
}
101108

102109
function isImpliedOrValid(attr) {
103110
return !(attr in opts) || Lib.validate(opts[attr], attrs[attr]);
104111
}
105112

106-
if(!isImpliedOrValid('width') || !isImpliedOrValid('height')) {
113+
if((!isImpliedOrValid('width') && opts.width !== null) ||
114+
(!isImpliedOrValid('height') && opts.height !== null)) {
107115
throw new Error('Height and width should be pixel values.');
108116
}
109117

@@ -132,8 +140,16 @@ function toImage(gd, opts) {
132140

133141
// extend layout with image options
134142
var layoutImage = Lib.extendFlat({}, layout);
135-
if(width) layoutImage.width = width;
136-
if(height) layoutImage.height = height;
143+
if(width) {
144+
layoutImage.width = width;
145+
} else if(opts.width === null && isNumeric(fullLayout.width)) {
146+
layoutImage.width = fullLayout.width;
147+
}
148+
if(height) {
149+
layoutImage.height = height;
150+
} else if(opts.height === null && isNumeric(fullLayout.height)) {
151+
layoutImage.height = fullLayout.height;
152+
}
137153

138154
// extend config for static plot
139155
var configImage = Lib.extendFlat({}, config, {

src/snapshot/download.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,10 @@
66
* LICENSE file in the root directory of this source tree.
77
*/
88

9-
109
'use strict';
1110

1211
var toImage = require('../plot_api/to_image');
13-
var Lib = require('../lib'); // for isIE
12+
var Lib = require('../lib');
1413
var fileSaver = require('./filesaver');
1514

1615
/** Plotly.downloadImage

test/jasmine/tests/modebar_test.js

+24-10
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ var destroyGraphDiv = require('../assets/destroy_graph_div');
1111
var selectButton = require('../assets/modebar_button');
1212
var failTest = require('../assets/fail_test');
1313

14-
1514
describe('ModeBar', function() {
1615
'use strict';
1716

@@ -960,10 +959,11 @@ describe('ModeBar', function() {
960959
Plotly.plot(gd, {data: [], layout: {}})
961960
.then(function() {
962961
selectButton(gd._fullLayout._modeBar, 'toImage').click();
963-
expect(Registry.call).toHaveBeenCalledWith('downloadImage', gd,
964-
{format: 'png'});
965-
done();
966-
});
962+
expect(Registry.call)
963+
.toHaveBeenCalledWith('downloadImage', gd, {format: 'png'});
964+
})
965+
.catch(failTest)
966+
.then(done);
967967
});
968968

969969
it('should accept overriding defaults', function(done) {
@@ -973,13 +973,27 @@ describe('ModeBar', function() {
973973
filename: 'x',
974974
unsupported: 'should not pass'
975975
}
976-
} })
976+
}})
977977
.then(function() {
978978
selectButton(gd._fullLayout._modeBar, 'toImage').click();
979-
expect(Registry.call).toHaveBeenCalledWith('downloadImage', gd,
980-
{format: 'svg', filename: 'x'});
981-
done();
982-
});
979+
expect(Registry.call)
980+
.toHaveBeenCalledWith('downloadImage', gd, {format: 'svg', filename: 'x'});
981+
})
982+
.catch(failTest)
983+
.then(done);
984+
});
985+
986+
it('should accept overriding defaults with null values', function(done) {
987+
Plotly.plot(gd, {data: [], layout: {}, config: {
988+
toImageButtonOptions: {width: null, height: null}
989+
}})
990+
.then(function() {
991+
selectButton(gd._fullLayout._modeBar, 'toImage').click();
992+
expect(Registry.call)
993+
.toHaveBeenCalledWith('downloadImage', gd, {format: 'png', width: null, height: null});
994+
})
995+
.catch(failTest)
996+
.then(done);
983997
});
984998
});
985999

test/jasmine/tests/toimage_test.js

+18
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,24 @@ describe('Plotly.toImage', function() {
115115
.then(done);
116116
});
117117

118+
it('should use width/height of graph div when width/height are set to *null*', function(done) {
119+
var fig = Lib.extendDeep({}, subplotMock);
120+
121+
gd.style.width = '832px';
122+
gd.style.height = '502px';
123+
124+
Plotly.plot(gd, fig.data, fig.layout).then(function() {
125+
expect(gd.layout.width).toBe(undefined, 'user layout width');
126+
expect(gd.layout.height).toBe(undefined, 'user layout height');
127+
expect(gd._fullLayout.width).toBe(832, 'full layout width');
128+
expect(gd._fullLayout.height).toBe(502, 'full layout height');
129+
})
130+
.then(function() { return Plotly.toImage(gd, {width: null, height: null}); })
131+
.then(function(url) { return assertSize(url, 832, 502); })
132+
.catch(failTest)
133+
.then(done);
134+
});
135+
118136
it('should create proper file type', function(done) {
119137
var fig = Lib.extendDeep({}, subplotMock);
120138

0 commit comments

Comments
 (0)