Skip to content

Commit 6344fa4

Browse files
committed
introduce per-basePlotModule toSVG step:
- so that the WebGL -> to <image> step can be generalize to custom base plot modules
1 parent e855521 commit 6344fa4

File tree

4 files changed

+93
-81
lines changed

4 files changed

+93
-81
lines changed

src/plots/geo/index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,27 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
7878
}
7979
}
8080
};
81+
82+
exports.toSVG = function(gd) {
83+
var fullLayout = gd._fullLayout,
84+
geoIds = Plots.getSubplotIds(fullLayout, 'geo'),
85+
size = fullLayout._size;
86+
87+
for(var i = 0; i < geoIds.length; i++) {
88+
var geoLayout = fullLayout[geoIds[i]],
89+
domain = geoLayout.domain,
90+
geoFramework = geoLayout._geo.framework;
91+
92+
geoFramework.attr('style', null);
93+
geoFramework
94+
.attr({
95+
x: size.l + size.w * domain.x[0] + geoLayout._marginX,
96+
y: size.t + size.h * (1 - domain.y[1]) + geoLayout._marginY,
97+
width: geoLayout._width,
98+
height: geoLayout._height
99+
});
100+
101+
fullLayout._geoimages.node()
102+
.appendChild(geoFramework.node());
103+
}
104+
};

src/plots/gl2d/index.js

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,9 @@
99

1010
'use strict';
1111

12-
var Plotly = require('../../plotly');
13-
1412
var Scene2D = require('./scene2d');
15-
16-
var Plots = Plotly.Plots;
13+
var Plots = require('../plots');
14+
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
1715

1816

1917
exports.name = 'gl2d';
@@ -80,3 +78,29 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
8078
}
8179
}
8280
};
81+
82+
exports.toSVG = function(gd) {
83+
var fullLayout = gd._fullLayout,
84+
subplotIds = Plots.getSubplotIds(fullLayout, 'gl2d'),
85+
size = fullLayout._size;
86+
87+
for(var i = 0; i < subplotIds.length; i++) {
88+
var subplot = fullLayout._plots[subplotIds[i]],
89+
scene = subplot._scene2d;
90+
91+
var imageData = scene.toImage('png');
92+
var image = fullLayout._glimages.append('svg:image');
93+
94+
image.attr({
95+
xmlns: xmlnsNamespaces.svg,
96+
'xlink:href': imageData,
97+
x: size.l,
98+
y: size.t,
99+
width: size.w,
100+
height: size.h,
101+
preserveAspectRatio: 'none'
102+
});
103+
104+
scene.destroy();
105+
}
106+
};

src/plots/gl3d/index.js

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
var Scene = require('./scene');
1313
var Plots = require('../plots');
14+
var xmlnsNamespaces = require('../../constants/xmlns_namespaces');
1415

1516
var axesNames = ['xaxis', 'yaxis', 'zaxis'];
1617

@@ -83,6 +84,33 @@ exports.clean = function(newFullData, newFullLayout, oldFullData, oldFullLayout)
8384
}
8485
};
8586

87+
exports.toSVG = function(gd) {
88+
var fullLayout = gd._fullLayout,
89+
sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'),
90+
size = fullLayout._size;
91+
92+
for(var i = 0; i < sceneIds.length; i++) {
93+
var sceneLayout = fullLayout[sceneIds[i]],
94+
domain = sceneLayout.domain,
95+
scene = sceneLayout._scene;
96+
97+
var imageData = scene.toImage('png');
98+
var image = fullLayout._glimages.append('svg:image');
99+
100+
image.attr({
101+
xmlns: xmlnsNamespaces.svg,
102+
'xlink:href': imageData,
103+
x: size.l + size.w * domain.x[0],
104+
y: size.t + size.h * (1 - domain.y[1]),
105+
width: size.w * (domain.x[1] - domain.x[0]),
106+
height: size.h * (domain.y[1] - domain.y[0]),
107+
preserveAspectRatio: 'none'
108+
});
109+
110+
scene.destroy();
111+
}
112+
};
113+
86114
// clean scene ids, 'scene1' -> 'scene'
87115
exports.cleanId = function cleanId(id) {
88116
if(!id.match(/^scene[0-9]*$/)) return;

src/snapshot/tosvg.js

Lines changed: 13 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111

1212
var d3 = require('d3');
1313

14-
var Plots = require('../plots/plots');
1514
var svgTextUtils = require('../lib/svg_text_utils');
1615
var Drawing = require('../components/drawing');
1716
var Color = require('../components/color');
@@ -20,80 +19,34 @@ var xmlnsNamespaces = require('../constants/xmlns_namespaces');
2019

2120

2221
module.exports = function toSVG(gd, format) {
22+
var fullLayout = gd._fullLayout,
23+
svg = fullLayout._paper,
24+
toppaper = fullLayout._toppaper,
25+
i;
2326

2427
// make background color a rect in the svg, then revert after scraping
2528
// all other alterations have been dealt with by properly preparing the svg
2629
// in the first place... like setting cursors with css classes so we don't
2730
// have to remove them, and providing the right namespaces in the svg to
2831
// begin with
29-
var fullLayout = gd._fullLayout,
30-
svg = fullLayout._paper,
31-
size = fullLayout._size,
32-
domain,
33-
i;
34-
3532
svg.insert('rect', ':first-child')
3633
.call(Drawing.setRect, 0, 0, fullLayout.width, fullLayout.height)
3734
.call(Color.fill, fullLayout.paper_bgcolor);
3835

39-
/* Grab the 3d scenes and rasterize em. Calculate their positions,
40-
* then insert them into the SVG element as images */
41-
var sceneIds = Plots.getSubplotIds(fullLayout, 'gl3d'),
42-
scene;
43-
44-
for(i = 0; i < sceneIds.length; i++) {
45-
scene = fullLayout[sceneIds[i]];
46-
domain = scene.domain;
47-
insertGlImage(fullLayout, scene._scene, {
48-
x: size.l + size.w * domain.x[0],
49-
y: size.t + size.h * (1 - domain.y[1]),
50-
width: size.w * (domain.x[1] - domain.x[0]),
51-
height: size.h * (domain.y[1] - domain.y[0])
52-
});
53-
}
54-
55-
// similarly for 2d scenes
56-
var subplotIds = Plots.getSubplotIds(fullLayout, 'gl2d'),
57-
subplot;
58-
59-
for(i = 0; i < subplotIds.length; i++) {
60-
subplot = fullLayout._plots[subplotIds[i]];
61-
insertGlImage(fullLayout, subplot._scene2d, {
62-
x: size.l,
63-
y: size.t,
64-
width: size.w,
65-
height: size.h
66-
});
67-
}
36+
// subplot-specific to-SVG methods
37+
// which notably add the contents of the gl-container
38+
// into the main svg node
39+
var basePlotModules = fullLayout._basePlotModules || [];
40+
for(i = 0; i < basePlotModules.length; i++) {
41+
var _module = basePlotModules[i];
6842

69-
// Grab the geos off the geo-container and place them in geoimages
70-
var geoIds = Plots.getSubplotIds(fullLayout, 'geo'),
71-
geoLayout,
72-
geoFramework;
73-
74-
for(i = 0; i < geoIds.length; i++) {
75-
geoLayout = fullLayout[geoIds[i]];
76-
domain = geoLayout.domain;
77-
geoFramework = geoLayout._geo.framework;
78-
79-
geoFramework.attr('style', null);
80-
geoFramework
81-
.attr({
82-
x: size.l + size.w * domain.x[0] + geoLayout._marginX,
83-
y: size.t + size.h * (1 - domain.y[1]) + geoLayout._marginY,
84-
width: geoLayout._width,
85-
height: geoLayout._height
86-
});
87-
88-
fullLayout._geoimages.node()
89-
.appendChild(geoFramework.node());
43+
if(_module.toSVG) _module.toSVG(gd);
9044
}
9145

92-
// now that we've got the 3d images in the right layer,
9346
// add top items above them assumes everything in toppaper is either
9447
// a group or a defs, and if it's empty (like hoverlayer) we can ignore it.
95-
if(fullLayout._toppaper) {
96-
var nodes = fullLayout._toppaper.node().childNodes;
48+
if(toppaper) {
49+
var nodes = toppaper.node().childNodes;
9750

9851
// make copy of nodes as childNodes prop gets mutated in loop below
9952
var topGroups = Array.prototype.slice.call(nodes);
@@ -164,20 +117,3 @@ module.exports = function toSVG(gd, format) {
164117

165118
return s;
166119
};
167-
168-
function insertGlImage(fullLayout, scene, opts) {
169-
var imageData = scene.toImage('png');
170-
171-
fullLayout._glimages.append('svg:image')
172-
.attr({
173-
xmlns: xmlnsNamespaces.svg,
174-
'xlink:href': imageData,
175-
x: opts.x,
176-
y: opts.y,
177-
width: opts.width,
178-
height: opts.height,
179-
preserveAspectRatio: 'none'
180-
});
181-
182-
scene.destroy();
183-
}

0 commit comments

Comments
 (0)