Skip to content

Commit b32aac0

Browse files
committed
fix toSVG for contour legend items & <linearGradient> colorbars
1 parent 89fae05 commit b32aac0

File tree

2 files changed

+96
-44
lines changed

2 files changed

+96
-44
lines changed

src/snapshot/tosvg.js

+7-2
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,20 @@ module.exports = function toSVG(gd, format, scale) {
116116
}
117117
});
118118

119-
svg.selectAll('.point,.scatterpts').each(function() {
119+
svg.selectAll('.point, .scatterpts, .legendfill>path, .legendlines>path, .cbfill').each(function() {
120120
var pt = d3.select(this);
121-
var fill = this.style.fill;
122121

123122
// similar to font family styles above,
124123
// we must remove " after the SVG DOM has been serialized
124+
var fill = this.style.fill;
125125
if(fill && fill.indexOf('url(') !== -1) {
126126
pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB));
127127
}
128+
129+
var stroke = this.style.stroke;
130+
if(stroke && stroke.indexOf('url(') !== -1) {
131+
pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB));
132+
}
128133
});
129134

130135
if(format === 'pdf' || format === 'eps') {

test/jasmine/tests/snapshot_test.js

+89-42
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
var Plotly = require('@lib/index');
2+
var Lib = require('@src/lib');
23

34
var d3 = require('d3');
45
var createGraphDiv = require('../assets/create_graph_div');
@@ -250,55 +251,101 @@ describe('Plotly.Snapshot', function() {
250251
});
251252
});
252253

253-
it('should handle quoted style properties', function(done) {
254-
Plotly.plot(gd, [{
255-
y: [1, 2, 1],
256-
marker: {
257-
gradient: {
258-
type: 'radial',
259-
color: '#fff'
260-
},
261-
color: ['red', 'blue', 'green']
262-
}
263-
}], {
264-
font: { family: 'Times New Roman' },
265-
showlegend: true
266-
})
267-
.then(function() {
268-
d3.selectAll('text').each(function() {
269-
expect(this.style.fontFamily).toEqual('\"Times New Roman\"');
270-
});
254+
describe('should handle quoted style properties', function() {
255+
function checkURL(actual, msg) {
256+
// which is enough tot check that toSVG did its job right
257+
expect((actual || '').substr(0, 6)).toBe('url(\"#', msg);
258+
}
271259

272-
d3.selectAll('.point,.scatterpts').each(function() {
273-
expect(this.style.fill.substr(0, 6)).toEqual('url(\"#');
274-
});
260+
it('- marker-gradient case', function(done) {
261+
Plotly.plot(gd, [{
262+
y: [1, 2, 1],
263+
marker: {
264+
gradient: {
265+
type: 'radial',
266+
color: '#fff'
267+
},
268+
color: ['red', 'blue', 'green']
269+
}
270+
}], {
271+
font: { family: 'Times New Roman' },
272+
showlegend: true
273+
})
274+
.then(function() {
275+
d3.selectAll('text').each(function() {
276+
expect(this.style.fontFamily).toEqual('\"Times New Roman\"');
277+
});
278+
279+
d3.selectAll('.point,.scatterpts').each(function() {
280+
checkURL(this.style.fill);
281+
});
282+
283+
return Plotly.Snapshot.toSVG(gd);
284+
})
285+
.then(function(svg) {
286+
var svgDOM = parser.parseFromString(svg, 'image/svg+xml');
287+
var i;
288+
289+
var textElements = svgDOM.getElementsByTagName('text');
290+
expect(textElements.length).toEqual(12);
291+
292+
for(i = 0; i < textElements.length; i++) {
293+
expect(textElements[i].style.fontFamily).toEqual('\"Times New Roman\"');
294+
}
275295

276-
return Plotly.Snapshot.toSVG(gd);
277-
})
278-
.then(function(svg) {
279-
var svgDOM = parser.parseFromString(svg, 'image/svg+xml');
280-
var i;
296+
var pointElements = svgDOM.getElementsByClassName('point');
297+
expect(pointElements.length).toEqual(3);
298+
299+
for(i = 0; i < pointElements.length; i++) {
300+
checkURL(pointElements[i].style.fill);
301+
}
281302

282-
var textElements = svgDOM.getElementsByTagName('text');
283-
expect(textElements.length).toEqual(12);
303+
var legendPointElements = svgDOM.getElementsByClassName('scatterpts');
304+
expect(legendPointElements.length).toEqual(1);
305+
checkURL(legendPointElements[0].style.fill);
306+
})
307+
.catch(failTest)
308+
.then(done);
309+
});
284310

285-
for(i = 0; i < textElements.length; i++) {
286-
expect(textElements[i].style.fontFamily).toEqual('\"Times New Roman\"');
287-
}
311+
it('- legend with contour items case', function(done) {
312+
var fig = Lib.extendDeep({}, require('@mocks/contour_legend.json'));
313+
var fillItemIndices = [0, 4, 5];
288314

289-
var pointElements = svgDOM.getElementsByClassName('point');
290-
expect(pointElements.length).toEqual(3);
315+
Plotly.plot(gd, fig)
316+
.then(function() { return Plotly.Snapshot.toSVG(gd); })
317+
.then(function(svg) {
318+
var svgDOM = parser.parseFromString(svg, 'image/svg+xml');
291319

292-
for(i = 0; i < pointElements.length; i++) {
293-
expect(pointElements[i].style.fill.substr(0, 6)).toEqual('url(\"#');
294-
}
320+
var fillItems = svgDOM.getElementsByClassName('legendfill');
321+
for(var i = 0; i < fillItemIndices.length; i++) {
322+
checkURL(fillItems[fillItemIndices[i]].firstChild.style.fill, 'fill gradient ' + i);
323+
}
295324

296-
var legendPointElements = svgDOM.getElementsByClassName('scatterpts');
297-
expect(legendPointElements.length).toEqual(1);
298-
expect(legendPointElements[0].style.fill.substr(0, 6)).toEqual('url(\"#');
299-
})
300-
.catch(failTest)
301-
.then(done);
325+
var lineItems = svgDOM.getElementsByClassName('legendlines');
326+
checkURL(lineItems[1].firstChild.style.stroke, 'stroke gradient');
327+
})
328+
.catch(failTest)
329+
.then(done);
330+
});
331+
332+
it('- colorbar case', function(done) {
333+
var fig = Lib.extendDeep({}, require('@mocks/16.json'));
334+
335+
Plotly.plot(gd, fig)
336+
.then(function() { return Plotly.Snapshot.toSVG(gd); })
337+
.then(function(svg) {
338+
var svgDOM = parser.parseFromString(svg, 'image/svg+xml');
339+
340+
var fillItems = svgDOM.getElementsByClassName('cbfill');
341+
expect(fillItems.length).toBe(1, '# of colorbars');
342+
for(var i = 0; i < fillItems.length; i++) {
343+
checkURL(fillItems[i].style.fill, 'fill gradient ' + i);
344+
}
345+
})
346+
.catch(failTest)
347+
.then(done);
348+
});
302349
});
303350

304351
it('should adapt *viewBox* attribute under *scale* option', function(done) {

0 commit comments

Comments
 (0)