Skip to content

Commit f58c670

Browse files
committed
add 'scale' to-image option
- which draw image data on bigger canvas (for png/jpeg/webp) - and scales svg using top-level width/height/viewBox attribute
1 parent ff8ecb1 commit f58c670

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed

src/plot_api/to_image.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ var attrs = {
4040
'Defaults to the value found in `layout.height`'
4141
].join(' ')
4242
},
43+
scale: {
44+
valType: 'number',
45+
min: 0,
46+
dflt: 1,
47+
description: [
48+
'...'
49+
].join(' ')
50+
},
4351
setBackground: {
4452
valType: 'any',
4553
dflt: false,
@@ -111,6 +119,7 @@ function toImage(gd, opts) {
111119
var format = coerce('format');
112120
var width = coerce('width');
113121
var height = coerce('height');
122+
var scale = coerce('scale');
114123
var setBackground = coerce('setBackground');
115124
var imageDataOnly = coerce('imageDataOnly');
116125

@@ -142,7 +151,7 @@ function toImage(gd, opts) {
142151

143152
function convert() {
144153
return new Promise(function(resolve, reject) {
145-
var svg = toSVG(clonedGd);
154+
var svg = toSVG(clonedGd, format, scale);
146155
var width = clonedGd._fullLayout.width;
147156
var height = clonedGd._fullLayout.height;
148157

@@ -164,6 +173,7 @@ function toImage(gd, opts) {
164173
format: format,
165174
width: width,
166175
height: height,
176+
scale: scale,
167177
canvas: canvas,
168178
svg: svg,
169179
// ask svgToImg to return a Promise

src/snapshot/svgtoimg.js

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ function svgToImg(opts) {
3333
}
3434

3535
var canvas = opts.canvas;
36+
var scale = opts.scale || 1;
37+
var w0 = opts.width || 150;
38+
var h0 = opts.height || 300;
39+
var w1 = scale * w0;
40+
var h1 = scale * h0;
41+
3642
var ctx = canvas.getContext('2d');
3743
var img = new Image();
3844

@@ -41,16 +47,16 @@ function svgToImg(opts) {
4147
// is not restricted to svg
4248
var url = 'data:image/svg+xml,' + encodeURIComponent(svg);
4349

44-
canvas.height = opts.height || 150;
45-
canvas.width = opts.width || 300;
50+
canvas.width = w1;
51+
canvas.height = h1;
4652

4753
img.onload = function() {
4854
var imgData;
4955

5056
// don't need to draw to canvas if svg
5157
// save some time and also avoid failure on IE
5258
if(format !== 'svg') {
53-
ctx.drawImage(img, 0, 0);
59+
ctx.drawImage(img, 0, 0, w1, h1);
5460
}
5561

5662
switch(format) {

src/snapshot/tosvg.js

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,21 @@ function xmlEntityEncode(str) {
3636
return str.replace(/&(?!\w+;|\#[0-9]+;| \#x[0-9A-F]+;)/g, '&');
3737
}
3838

39-
module.exports = function toSVG(gd, format) {
40-
var fullLayout = gd._fullLayout,
41-
svg = fullLayout._paper,
42-
toppaper = fullLayout._toppaper,
43-
i;
39+
module.exports = function toSVG(gd, format, scale) {
40+
var fullLayout = gd._fullLayout;
41+
var svg = fullLayout._paper;
42+
var toppaper = fullLayout._toppaper;
43+
var width = fullLayout.width;
44+
var height = fullLayout.height;
45+
var i;
4446

4547
// make background color a rect in the svg, then revert after scraping
4648
// all other alterations have been dealt with by properly preparing the svg
4749
// in the first place... like setting cursors with css classes so we don't
4850
// have to remove them, and providing the right namespaces in the svg to
4951
// begin with
5052
svg.insert('rect', ':first-child')
51-
.call(Drawing.setRect, 0, 0, fullLayout.width, fullLayout.height)
53+
.call(Drawing.setRect, 0, 0, width, height)
5254
.call(Color.fill, fullLayout.paper_bgcolor);
5355

5456
// subplot-specific to-SVG methods
@@ -137,6 +139,12 @@ module.exports = function toSVG(gd, format) {
137139
svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns', xmlnsNamespaces.svg);
138140
svg.node().setAttributeNS(xmlnsNamespaces.xmlns, 'xmlns:xlink', xmlnsNamespaces.xlink);
139141

142+
if(format === 'svg' && scale) {
143+
svg.attr('width', scale * width);
144+
svg.attr('height', scale * height);
145+
svg.attr('viewBox', '0 0 ' + width + ' ' + height);
146+
}
147+
140148
var s = new window.XMLSerializer().serializeToString(svg.node());
141149
s = htmlEntityDecode(s);
142150
s = xmlEntityEncode(s);

0 commit comments

Comments
 (0)