From 55d76b2688f0016f608e5924e589be98e2c3fa67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Tue, 24 Dec 2019 14:25:37 -0500 Subject: [PATCH] use fullLayout._gradientUrlQueryParts stash to fix gradient URLs ... during image exports, instead of having hard-coded list of query-selectors in toSVG routine. --- src/components/drawing/index.js | 20 ++++++++++++++++--- src/snapshot/tosvg.js | 34 ++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/src/components/drawing/index.js b/src/components/drawing/index.js index b94498b7923..e22567a95c6 100644 --- a/src/components/drawing/index.js +++ b/src/components/drawing/index.js @@ -300,9 +300,10 @@ drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) { } } - var fullID = 'g' + gd._fullLayout._uid + '-' + gradientID; + var fullLayout = gd._fullLayout; + var fullID = 'g' + fullLayout._uid + '-' + gradientID; - var gradient = gd._fullLayout._defs.select('.gradients') + var gradient = fullLayout._defs.select('.gradients') .selectAll('#' + fullID) .data([type + colorStops.join(';')], Lib.identity); @@ -333,6 +334,13 @@ drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) { sel.style(prop, getFullUrl(fullID, gd)) .style(prop + '-opacity', null); + + var className2query = function(s) { + return '.' + s.attr('class').replace(/\s/g, '.'); + }; + var k = className2query(d3.select(sel.node().parentNode)) + + '>' + className2query(sel); + fullLayout._gradientUrlQueryParts[k] = 1; }; /* @@ -343,8 +351,14 @@ drawing.gradient = function(sel, gd, gradientID, type, colorscale, prop) { * The upside of this is arbitrary points can share gradient defs */ drawing.initGradients = function(gd) { - var gradientsGroup = Lib.ensureSingle(gd._fullLayout._defs, 'g', 'gradients'); + var fullLayout = gd._fullLayout; + + var gradientsGroup = Lib.ensureSingle(fullLayout._defs, 'g', 'gradients'); gradientsGroup.selectAll('linearGradient,radialGradient').remove(); + + // initialize stash of query parts filled in Drawing.gradient, + // used to fix URL strings during image exports + fullLayout._gradientUrlQueryParts = {}; }; diff --git a/src/snapshot/tosvg.js b/src/snapshot/tosvg.js index a4dc988a0f2..f35fa17fc86 100644 --- a/src/snapshot/tosvg.js +++ b/src/snapshot/tosvg.js @@ -115,21 +115,29 @@ module.exports = function toSVG(gd, format, scale) { } }); - svg.selectAll('.point, .scatterpts, .legendfill>path, .legendlines>path, path.legend3dandfriends, .cbfill').each(function() { - var pt = d3.select(this); - - // similar to font family styles above, - // we must remove " after the SVG DOM has been serialized - var fill = this.style.fill; - if(fill && fill.indexOf('url(') !== -1) { - pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); - } - var stroke = this.style.stroke; - if(stroke && stroke.indexOf('url(') !== -1) { - pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + if(fullLayout._gradientUrlQueryParts) { + var queryParts = []; + for(var k in fullLayout._gradientUrlQueryParts) queryParts.push(k); + + if(queryParts.length) { + svg.selectAll(queryParts.join(',')).each(function() { + var pt = d3.select(this); + + // similar to font family styles above, + // we must remove " after the SVG DOM has been serialized + var fill = this.style.fill; + if(fill && fill.indexOf('url(') !== -1) { + pt.style('fill', fill.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } + + var stroke = this.style.stroke; + if(stroke && stroke.indexOf('url(') !== -1) { + pt.style('stroke', stroke.replace(DOUBLEQUOTE_REGEX, DUMMY_SUB)); + } + }); } - }); + } if(format === 'pdf' || format === 'eps') { // these formats make the extra line MathJax adds around symbols look super thick in some cases