Skip to content

Commit 54094d6

Browse files
committed
mv tosvg.js shelly/ --> ./src/
1 parent b3a8a39 commit 54094d6

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

src/snapshot/tosvg.js

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
'use strict';
2+
3+
var Plotly = require('../plotly'),
4+
d3 = require('d3');
5+
6+
module.exports = function toSVG(gd, format) {
7+
8+
// make background color a rect in the svg, then revert after scraping
9+
// all other alterations have been dealt with by properly preparing the svg
10+
// in the first place... like setting cursors with css classes so we don't
11+
// have to remove them, and providing the right namespaces in the svg to
12+
// begin with
13+
var fullLayout = gd._fullLayout,
14+
svg = fullLayout._paper,
15+
size = fullLayout._size,
16+
domain,
17+
i;
18+
19+
svg.insert('rect', ':first-child')
20+
.call(Plotly.Drawing.setRect, 0, 0, fullLayout.width, fullLayout.height)
21+
.call(Plotly.Color.fill, fullLayout.paper_bgcolor);
22+
23+
/* Grab the 3d scenes and rasterize em. Calculate their positions,
24+
* then insert them into the SVG element as images */
25+
var sceneIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl3d'),
26+
scene;
27+
28+
for(i = 0; i < sceneIds.length; i++) {
29+
scene = fullLayout[sceneIds[i]];
30+
domain = scene.domain;
31+
insertGlImage(fullLayout, scene._scene, {
32+
x: size.l + size.w * domain.x[0],
33+
y: size.t + size.h * (1 - domain.y[1]),
34+
width: size.w * (domain.x[1] - domain.x[0]),
35+
height: size.h * (domain.y[1] - domain.y[0])
36+
});
37+
}
38+
39+
// similarly for 2d scenes
40+
var subplotIds = Plotly.Plots.getSubplotIds(fullLayout, 'gl2d'),
41+
subplot;
42+
43+
for(i = 0; i < subplotIds.length; i++) {
44+
subplot = fullLayout._plots[subplotIds[i]];
45+
insertGlImage(fullLayout, subplot._scene2d, {
46+
x: size.l,
47+
y: size.t,
48+
width: size.w,
49+
height: size.h
50+
});
51+
}
52+
53+
// Grab the geos off the geo-container and place them in geoimages
54+
var geoIds = Plotly.Plots.getSubplotIds(fullLayout, 'geo'),
55+
geoLayout,
56+
geoFramework;
57+
58+
for(i = 0; i < geoIds.length; i++) {
59+
geoLayout = fullLayout[geoIds[i]];
60+
domain = geoLayout.domain;
61+
geoFramework = geoLayout._geo.framework;
62+
63+
geoFramework.attr('style', null);
64+
geoFramework
65+
.attr({
66+
x: size.l + size.w * domain.x[0] + geoLayout._marginX,
67+
y: size.t + size.h * (1 - domain.y[1]) + geoLayout._marginY,
68+
width: geoLayout._width,
69+
height: geoLayout._height
70+
});
71+
72+
fullLayout._geoimages.node()
73+
.appendChild(geoFramework.node());
74+
}
75+
76+
// now that we've got the 3d images in the right layer, add top items above them
77+
// assumes everything in toppaper is a group, and if it's empty (like hoverlayer)
78+
// we can ignore it
79+
if(fullLayout._toppaper) {
80+
var topGroups = fullLayout._toppaper.node().childNodes,
81+
topGroup;
82+
for(i = 0; i < topGroups.length; i++) {
83+
topGroup = topGroups[i];
84+
if(topGroup.childNodes.length) svg.node().appendChild(topGroup);
85+
}
86+
}
87+
88+
// in case the svg element had an explicit background color, remove this
89+
// we want the rect to get the color so it's the right size; svg bg will
90+
// fill whatever container it's displayed in regardless of plot size.
91+
svg.node().style.background = '';
92+
93+
svg.selectAll('text')
94+
.attr({'data-unformatted': null})
95+
.each(function() {
96+
// hidden text is pre-formatting mathjax, the browser ignores it but it can still confuse batik
97+
var txt = d3.select(this);
98+
if(txt.style('visibility') === 'hidden') {
99+
txt.remove();
100+
return;
101+
}
102+
103+
// I've seen font-family styles with non-escaped double quotes in them - breaks the
104+
// serialized svg because the style attribute itself is double-quoted!
105+
// Is this an IE thing? Any other attributes or style elements that can have quotes in them?
106+
// TODO: this looks like a noop right now - what happened to it?
107+
var ff = txt.style('font-family');
108+
if(ff && ff.indexOf('"') !== -1) txt.style('font-family', ff.replace(/"/g, '"'));
109+
});
110+
111+
if(format === 'pdf' || format === 'eps') {
112+
// these formats make the extra line MathJax adds around symbols look super thick in some cases
113+
// it looks better if this is removed entirely.
114+
svg.selectAll('#MathJax_SVG_glyphs path')
115+
.attr('stroke-width', 0);
116+
}
117+
118+
// fix for IE namespacing quirk?
119+
// http://stackoverflow.com/questions/19610089/unwanted-namespaces-on-svg-markup-when-using-xmlserializer-in-javascript-with-ie
120+
svg.node().setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns', 'http://www.w3.org/2000/svg');
121+
svg.node().setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:xlink', 'http://www.w3.org/1999/xlink');
122+
123+
var s = new window.XMLSerializer().serializeToString(svg.node());
124+
s = Plotly.util.html_entity_decode(s);
125+
s = Plotly.util.xml_entity_encode(s);
126+
127+
return s;
128+
};
129+
130+
function insertGlImage(fullLayout, scene, opts) {
131+
var imageData = scene.toImage('png');
132+
133+
fullLayout._glimages.append('svg:image')
134+
.attr({
135+
xmlns:'http://www.w3.org/2000/svg',
136+
'xlink:xlink:href': imageData, // odd d3 quirk, need namespace twice
137+
x: opts.x,
138+
y: opts.y,
139+
width: opts.width,
140+
height: opts.height,
141+
preserveAspectRatio: 'none'
142+
});
143+
144+
scene.destroy();
145+
}

0 commit comments

Comments
 (0)