关于javascript:服务器端d3 – 将SVG编码为Base64图像

Server Side d3 - Encoding SVG as a Base64 Image

我正在尝试将d3图表编码为base64图像,以便在HTML电子邮件中使用。

到目前为止,我有:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
var express = require('express');
var app = express();
var jsdom = require('jsdom');

app.get('/chart', function (request, response) {
    try {
        jsdom.env(
           "<html><body><svg id="svg"></svg></body></html>",
            ['http://d3js.org/d3.v3.min.js'],
            function (err, window) {
                var svg = window.d3.select("svg")
                    .attr("width", 100)
                    .attr("height", 100);

                svg.append("rect")
                    .attr("x", 10)
                    .attr("y", 10)
                    .attr("width", 80)
                    .attr("height", 80)
                    .style("fill","orange");

                var encoded = ...; // How do I now encode this?

                response.send({
                   "html": window.d3.select("body").html(),
                   "encoded": encoded
                });
            }
        );
    } catch (err) {
        console.error(err);
    }
});

// Run Server
var port = process.env.PORT || 8305;
var server = app.listen(port, function () {
    var host = server.address().address;
    console.log('App listening at http://%s:%s', host, port);
});

这将输出SVG HTML,这很有用,但我也希望有第二个响应字段encoded,其中应包含如下内容,我可以在HTML电子邮件中使用:

1
"encoded":"data:image/png;base64,iVBORw0KGgoAAAANSUhEU...etc"

如何编码这个SVG?如果可能的话,我希望避免任何文件写入,直接从SVG到编码图像。另外,我知道你可以在电子邮件中使用SVG,但我更希望它是一种编码的图像格式。谢谢!


将根节点的"xmlns"属性设置为document.attr()节点的节点的"http://www.w3.org/2000/svg"

data URI方案包括

1
data:[<media type>][;base64],<data>

因为我们知道将是image/svg+xml,并且我们希望base64表示结果数据,所以我们可以定义一个变量,将base64表示的连接到该变量。

1
let data ="data:image/svg+xml;base64,";

然后得到元素的.outerHTML

1
2
// optionally preceded by `XML` declaration `<?xml version="1.0" standalone="yes"?>`
let svgString = svg[0][0].outerHTML;

调用btoa(),参数为svgString

The btoa(data) method must throw an"InvalidCharacterError"
DOMException if data contains any character whose code point is
greater than U+00FF. Otherwise, the user agent must convert data to
a sequence of octets whose nth octet is the eight-bit representation
of the code point of the n th character of data, and then must
apply the base64 algorithm to that sequence of octets, and return the
result. [RFC4648]

1
2
3
4
5
6
7
8
let base64 = window.btoa(svgString);
// concatenate `data` and `base64`
let dataURI = data + base64;

response.send({
               "html": window.d3.select("body").html(),
               "encoded": dataURI
             });

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let svg = window.d3.select("svg")
  .attr("xmlns","http://www.w3.org/2000/svg")
  .attr("width", 100)
  .attr("height", 100);

svg.append("rect")
  .attr("x", 10)
  .attr("y", 10)
  .attr("width", 80)
  .attr("height", 80)
  .style("fill","orange");

let data ="data:image/svg+xml;base64,";
let svgString = svg[0][0].outerHTML;
let base64 = window.btoa(svgString);
let dataURI = data + base64;

console.log(dataURI);

document.querySelector("iframe").src = dataURI;
1
2
3
<script src="https://d3js.org/d3.v3.min.js">
<svg></svg>
<iframe></iframe>