D3: SVG可下载,但属性消失了。

时间:2022-01-17 08:29:16

I need to make my D3-created SVG charts downloadable. I found one answer to this question that suggested encoding SVG's XML to base64, but then I found this post that said plain text should be OK too, so I came up with something like this:

我需要让我的d3创建的SVG图表可下载。我找到了这个问题的答案,建议将SVG的XML编码到base64,但是后来我发现这篇文章说纯文本应该也可以,所以我想到了这样的东西:

<!DOCTYPE html>
<html>
<head>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
  <script>
    var data = [22, 33, 11, 55, 44];
    var svg = d3.select('body').append('svg')
      .attr('id', 'chart')
      .attr('version', '1.1')
      .attr('xmlns', 'http://www.w3.org/2000/svg')
      .attr('width', 600)
      .attr('height', 400)
      .style('background-color', 'powderblue')
      .selectAll('circle')
        .data(data)
        .enter().append('circle')
          .attr('cx', function(d) { return 8*d; })
          .attr('cy', function(d) { return 4*d; })
          .attr('r', function(d) { return d; })
          .style('fill', function(d) { return d3.rgb(2*d, 4*d, 3*d); })
    ;
    d3.select('body').append('a')
      .attr('href-lang', 'image/svg+xml')
      .attr('href', 'data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg">' + unescape(svg.node().parentNode.innerHTML) + '</svg>')
      .text('Download')
    ;
  </script>
</body>
</html>

The above code works partially, because the download link can be opened in the browser or downloaded to a file, but in each case only the circles are visible and all else (ie. width, height, bg color) is lost, so the SVG is only properly displayed in the original HTML page. What is the right way to get the full code of SVG created with D3? I tried svg.html() and d3.select(svg).html(), but it returns null.

上面的代码部分工作,因为下载链接可以在浏览器中打开或者下载到一个文件,但是在每个情况下,只有圆圈是可见的和其他的(ie)。宽度、高度、bg颜色)丢失,因此SVG只能在原始HTML页面中正确显示。用D3创建完整的SVG代码的正确方法是什么?我尝试了svg.html()和d3.select(svg).html(),但它返回null。

1 个解决方案

#1


4  

You could try saving the parent's outerHTML.
.attr('href', 'data:image/svg+xml;utf8,' + unescape(svg.node().parentNode.outerHTML))

您可以尝试保存父的outerHTML. .attr('href', 'data:image/svg+xml;utf8,' + unescape(svg.node(). parentnode.outerhtml))

<!DOCTYPE html>
<html>
<head>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
  <script>
    var data = [22, 33, 11, 55, 44];
    var svg = d3.select('body').append('svg')
      .attr('id', 'chart')
      .attr('version', '1.1')
      .attr('xmlns', 'http://www.w3.org/2000/svg')
      .attr('width', 600)
      .attr('height', 400)
      .style('background-color', 'powderblue')
      .selectAll('circle')
        .data(data)
        .enter().append('circle')
          .attr('cx', function(d) { return 8*d; })
          .attr('cy', function(d) { return 4*d; })
          .attr('r', function(d) { return d; })
          .style('fill', function(d) { return d3.rgb(2*d, 4*d, 3*d); })
    ;
    d3.select('body').append('a')
      .attr('href-lang', 'image/svg+xml')
      .attr('href', 'data:image/svg+xml; charset=utf8, ' + unescape(svg.node().parentNode.outerHTML))
      .text('Download')
    ;
  </script>
</body>
</html>

Ps: You may also want to add the download attribute on your link, for recent browsers users can directly download it as a file.

Ps:你也可以在你的链接上添加下载属性,因为最近的浏览器用户可以直接下载它作为文件。

PPs: To force the width height of the new file, you should set the viewbox attribute of your svg

PPs:要强制新文件的宽度高度,您应该设置svg的viewbox属性。

PPPs: To have a fully valid svg file (i.e with DOCTYPE set etc.) I think you will have to add those four more lines :

PPPs:拥有一个完全有效的svg文件(我。我认为你必须加上这四行:

var svgDocType = document.implementation.createDocumentType('svg',  "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
var svgDoc= document.implementation.createDocument ('http://www.w3.org/2000/svg', 'svg', svgDocType);
svgDoc.replaceChild(svg.node().parentNode.cloneNode(true), svgDoc.documentElement);
svgData = (new XMLSerializer()).serializeToString(svgDoc);

var data = [22, 33, 11, 55, 44];
    var svg = d3.select('body').append('svg')
      .attr('id', 'chart')
      .attr('version', '1.1')
      .attr('xmlns', 'http://www.w3.org/2000/svg')
      .attr('width', 600)
      .attr('height', 400)
      .style('background-color', 'powderblue')
      .selectAll('circle')
        .data(data)
        .enter().append('circle')
          .attr('cx', function(d) { return 8*d; })
          .attr('cy', function(d) { return 4*d; })
          .attr('r', function(d) { return d; })
          .style('fill', function(d) { return d3.rgb(2*d, 4*d, 3*d); })
    ;
    var svgDocType = document.implementation.createDocumentType('svg',  "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
    var svgDoc= document.implementation.createDocument ('http://www.w3.org/2000/svg', 'svg', svgDocType);
    svgDoc.replaceChild(svg.node().parentNode.cloneNode(true), svgDoc.documentElement);
    svgData = (new XMLSerializer()).serializeToString(svgDoc);
    d3.select('body').append('a')
      .attr('href-lang', 'image/svg+xml')
      .attr('href', 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData))
      .text('Download')
    ;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

#1


4  

You could try saving the parent's outerHTML.
.attr('href', 'data:image/svg+xml;utf8,' + unescape(svg.node().parentNode.outerHTML))

您可以尝试保存父的outerHTML. .attr('href', 'data:image/svg+xml;utf8,' + unescape(svg.node(). parentnode.outerhtml))

<!DOCTYPE html>
<html>
<head>
  <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
</head>
<body>
  <script>
    var data = [22, 33, 11, 55, 44];
    var svg = d3.select('body').append('svg')
      .attr('id', 'chart')
      .attr('version', '1.1')
      .attr('xmlns', 'http://www.w3.org/2000/svg')
      .attr('width', 600)
      .attr('height', 400)
      .style('background-color', 'powderblue')
      .selectAll('circle')
        .data(data)
        .enter().append('circle')
          .attr('cx', function(d) { return 8*d; })
          .attr('cy', function(d) { return 4*d; })
          .attr('r', function(d) { return d; })
          .style('fill', function(d) { return d3.rgb(2*d, 4*d, 3*d); })
    ;
    d3.select('body').append('a')
      .attr('href-lang', 'image/svg+xml')
      .attr('href', 'data:image/svg+xml; charset=utf8, ' + unescape(svg.node().parentNode.outerHTML))
      .text('Download')
    ;
  </script>
</body>
</html>

Ps: You may also want to add the download attribute on your link, for recent browsers users can directly download it as a file.

Ps:你也可以在你的链接上添加下载属性,因为最近的浏览器用户可以直接下载它作为文件。

PPs: To force the width height of the new file, you should set the viewbox attribute of your svg

PPs:要强制新文件的宽度高度,您应该设置svg的viewbox属性。

PPPs: To have a fully valid svg file (i.e with DOCTYPE set etc.) I think you will have to add those four more lines :

PPPs:拥有一个完全有效的svg文件(我。我认为你必须加上这四行:

var svgDocType = document.implementation.createDocumentType('svg',  "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
var svgDoc= document.implementation.createDocument ('http://www.w3.org/2000/svg', 'svg', svgDocType);
svgDoc.replaceChild(svg.node().parentNode.cloneNode(true), svgDoc.documentElement);
svgData = (new XMLSerializer()).serializeToString(svgDoc);

var data = [22, 33, 11, 55, 44];
    var svg = d3.select('body').append('svg')
      .attr('id', 'chart')
      .attr('version', '1.1')
      .attr('xmlns', 'http://www.w3.org/2000/svg')
      .attr('width', 600)
      .attr('height', 400)
      .style('background-color', 'powderblue')
      .selectAll('circle')
        .data(data)
        .enter().append('circle')
          .attr('cx', function(d) { return 8*d; })
          .attr('cy', function(d) { return 4*d; })
          .attr('r', function(d) { return d; })
          .style('fill', function(d) { return d3.rgb(2*d, 4*d, 3*d); })
    ;
    var svgDocType = document.implementation.createDocumentType('svg',  "-//W3C//DTD SVG 1.1//EN", "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd");
    var svgDoc= document.implementation.createDocument ('http://www.w3.org/2000/svg', 'svg', svgDocType);
    svgDoc.replaceChild(svg.node().parentNode.cloneNode(true), svgDoc.documentElement);
    svgData = (new XMLSerializer()).serializeToString(svgDoc);
    d3.select('body').append('a')
      .attr('href-lang', 'image/svg+xml')
      .attr('href', 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData))
      .text('Download')
    ;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>