D3js: how to generate standalone SVG files? (Nodejs)

青春壹個敷衍的年華 提交于 2019-12-29 14:23:45

问题


Given a D3js code, such as:

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>

How to generate a correct stand alone *.svg file with my D3js code & NodeJS ?


回答1:


Github repository svgcreator.node.js to try out.


D3 doesn't care at all what actually generate your SVG. The main problem with creating only SVG is that you can't have Javascript then, which of course means that you can't use D3. Apart from this fundamental no-no, there's nothing stopping you :)

Proof of concept: Inspired by the other answer, here's some proof-of-concept code using jsdom.

1. Install NodeJS (1).

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

2. Install jsdom using the Node Packages Manager (2):

$npm install jsdom

3. Wrap your D3js code within some jsdom code, paste into a jsdom.node.js file :

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. Run in terminal

$node jsdom.node.js > test.svg

The stdout output is the SVG, which is then injected into a test.svg file. Job done.

As Gilly points out in the comments, you may need version 3 of jsdom for this to work.




回答2:


I recently wanted to do just that and asked a question here. I was pointed to phantomJS. Using PhantomJS, I created a 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>

Then I run

phantomjs svggen.js > svgFile.svg

The resulting svgFile.svg is a standalone SVG File. For d3cloud check this.




回答3:


node.js is the way to go. You can install d3 directly with npm. (It will also add jsdom as a dependency to provide a "fake" DOM.) After the d3 code generates the SVG, just grab its contents and write to a file.




回答4:


if you donot want to use node.js , then use phantomJs , here you can find a demo https://github.com/subramanya2107/d3js-phantomjs-demo.git




回答5:


Here's a very short node script that will output an svg to stdout generated with d3.js.

#!/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



来源:https://stackoverflow.com/questions/19080929/d3js-how-to-generate-standalone-svg-files-nodejs

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!