D3js:如何生成独立的SVG文件?(Nodejs)

23

给定一个 D3js 代码例如:

var square= function() {
        var svg = window.d3.select("body")
            .append("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");
    }
square();
svg { border: 1px solid grey;} /* just to visualized the svg file's area */
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<body></body>

如何使用我的D3js代码和NodeJS生成正确的独立*.svg文件?


请参阅 Exporting D3.js graphs to static SVG files, programmatically 中的 #PhantomJS 方向。 - Hugolpz
May 可以与 将(png?)图像文件转换为data:image 的代码很好地配合使用,以嵌入SVG :) - Hugolpz
5个回答

26

尝试使用Github存储库 svgcreator.node.js


D3并不关心您实际生成的SVG是什么。创建仅限SVG的主要问题是您无法使用Javascript,这当然意味着您无法使用D3。除了这个基本的不可能,没有任何事情能阻止您 :)

概念验证: 受到其他答案的启发,以下是使用jsdom的一些概念验证代码。

1. 安装NodeJS (1).

curl http://npmjs.org/install.sh | sh       #this should work (not tested)

2. 使用Node包管理器安装jsdom (2):

$npm install jsdom

3. 将您的D3js代码嵌入到一些jsdom代码中,粘贴到一个jsdom.node.js文件中 :

var jsdom = require('jsdom');

jsdom.env(
  "<html><body></body></html>",
  [ 'http://d3js.org/d3.v3.min.js' ],
  function (err, window) {
    var svg = window.d3.select("body")
        .append("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");
// PRINT OUT:
    console.log(window.d3.select("body").html());
//  fs.writeFileSync('out.svg', window.d3.select("body").html()); // or this
  }
);

4. 在终端中运行

$node jsdom.node.js > test.svg

stdout输出是SVG,然后将其注入到test.svg文件中。工作完成。

正如Gilly在评论中指出的,你可能需要jsdom的第3版本才能使其工作。


你好,Lars。我是JS的初学者,有些不理解。你是否考虑使用Node.js来解决问题?将我的D3.js代码放入一个纯粹的.js文件中,在Node中运行,然后获取输出结果? - Hugolpz
我想使用D3js输出数百或数千个类似这个的文件。如果我可以直接输出SVG文件会更好。 - Hugolpz
我想通过编程方式获取 .svg 文件。生成一个 HTML 页面,然后在页面上点击下载文件的方式不适合我们需要生成数百甚至数千个文件的情况。最高估计需要生成 20,000 个 SVG 文件。 - Hugolpz
抱歉突然在这里留言,但是你的示例中的下载按钮在Safari 6.0.5的Mac OS上无法使用。 - tomtomtom
鉴于此答案得到的支持很少(只有我们两个),我认为我们是唯一能理解这有多酷的人!:D - Hugolpz
显示剩余11条评论

4
这是一个非常简短的Node脚本,它将使用d3.js生成一个SVG,并将其输出到标准输出。
#!/usr/bin/env node

var d3 = require("d3"),
    jsdom = require("jsdom").jsdom;

var body = d3.select(jsdom().documentElement).select("body");

var svg = body.append("svg");
process.stdout.write(body.node().innerHTML);

Link to snippet on bl.ocks.org


3
我最近想要做的就是这个,然后在这里提问:(链接已移除)。有人指引我使用PhantomJS。通过使用PhantomJS,我创建了一个JS文件 -

svggen.js:

var page = require('webpage').create(),
    url = 'http://www.example.com/wordcloud.html';

page.open(url, function (status) {
    if (status !== 'success') {
        console.log('Unable to access network');
    } else {
        var svgData = page.evaluate(function(s){
                var serializer = new XMLSerializer();
                var element = document.getElementById("svg1");
                return serializer.serializeToString(element);
        });
        console.log("<?xml version=\"1.0\"?>"+svgData);
    }
    phantom.exit();
});

wordcloud.html:

<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="d3.min.js"></script>
<script src="d3.layout.cloud.js"></script>
<script>
  var fill = d3.scale.category20();

  d3.layout.cloud().size([500, 800])
      .words([
        "Hello", "world", "normally", "you", "want", "more", "words",
        "than", "this"].map(function(d) {
        return {text: d, size: 10 + Math.random() * 90};
      }))
      .padding(5)
      .rotate(function() { return ~~(Math.random() * 2) * 90; })
      .font("Impact")
      .fontSize(function(d) { return d.size; })
      .on("end", draw)
      .start();

  function draw(words) {
    d3.select("body").append("svg")
        .attr("width", 500)
        .attr("height", 800)
        .attr("id","svg1")
        .attr("xmlns","http://www.w3.org/2000/svg")
        .attr("xmlns:xlink","http://www.w3.org/1999/xlink")
      .append("g")
        .attr("transform", "translate(150,150)")
      .selectAll("text")
        .data(words)
      .enter().append("text")
        .style("font-size", function(d) { return d.size + "px"; })
        .style("font-family", "Impact")
        .style("fill", function(d, i) { return fill(i); })
        .attr("text-anchor", "middle")
        .attr("transform", function(d) {
          return "translate(" + [d.x, d.y] + ")rotate(" + d.rotate + ")";
        })
        .text(function(d) { return d.text; });
  }
</script>
</body></html>

然后我运行。
phantomjs svggen.js > svgFile.svg

生成的svgFile.svg是一个独立的SVG文件。如需了解d3cloud,请查看链接。


2

Node.js是一个不错的选择。你可以直接通过npm安装d3。(这也会将jsdom作为依赖项添加到其中,以提供“虚拟”DOM。) 当d3代码生成SVG后,只需获取其内容并写入文件即可。


4
将图表插入到 HTML 的 <div> 中,然后使用 $('whatever').html() 获取其内容。利用 Node.js 的文件系统(fs)将内容写入文件中。(如果您需要有人为您编写代码,请发送私信给我。我的收费是 $90/小时。) - Stephen Thomas
我设计了这个项目并提出了建议,但它目前还没有资金支持。不过感谢您的关注。 - Hugolpz

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接