Skip to content

Instantly share code, notes, and snippets.

@tomgp
Last active February 16, 2024 22:08
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save tomgp/c99a699587b5c5465228 to your computer and use it in GitHub Desktop.
Save tomgp/c99a699587b5c5465228 to your computer and use it in GitHub Desktop.
Server side SVG via D3 & jsdom

a very simple example

Get going:

npm install
node pie.js

example usage in index.js

{
"name": "simple-node-d3",
"version": "1.0.0",
"description": "Serverside SVG via D3 & jsdom",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "tom.g.pearson@gmail.com",
"license": "ISC",
"dependencies": {
"d3": "^3.5.5",
"jsdom": "^3.1.2"
}
}
var fs = require('fs');
var d3 = require('d3');
var jsdom = require('jsdom');
var chartWidth = 500, chartHeight = 500;
var arc = d3.svg.arc()
.outerRadius(chartWidth/2 - 10)
.innerRadius(0);
var colours = ['#F00','#000','#000','#000','#000','#000','#000','#000','#000'];
module.exports = function( pieData, outputLocation ){
if(!pieData) pieData = [12,31];
if(!outputLocation) outputLocation = 'test.svg';
jsdom.env({
html:'',
features:{ QuerySelector:true }, //you need query selector for D3 to work
done:function(errors, window){
window.d3 = d3.select(window.document); //get d3 into the dom
//do yr normal d3 stuff
var svg = window.d3.select('body')
.append('div').attr('class','container') //make a container div to ease the saving process
.append('svg')
.attr({
xmlns:'http://www.w3.org/2000/svg',
width:chartWidth,
height:chartHeight
})
.append('g')
.attr('transform','translate(' + chartWidth/2 + ',' + chartWidth/2 + ')');
svg.selectAll('.arc')
.data( d3.layout.pie()(pieData) )
.enter()
.append('path')
.attr({
'class':'arc',
'd':arc,
'fill':function(d,i){
return colours[i];
},
'stroke':'#fff'
});
//write out the children of the container div
fs.writeFileSync(outputLocation, window.d3.select('.container').html()) //using sync to keep the code simple
}
});
}
if (require.main === module) {
module.exports();
}
@misha-erm
Copy link

Hi, thanks for your example, but I'm experiencing next error using it with the latest d3 and jsdom:
var arc = d3.svg.arc()
^

TypeError: Cannot read property 'arc' of undefined

Any ideas?

@dam1r89
Copy link

dam1r89 commented Dec 12, 2017

Example that works with latest version of d3 and jsdom

var fs = require('fs');
var d3 = require('d3');
var JSDOM = require('jsdom').JSDOM;

var chartWidth = 500,
    chartHeight = 500;

var arc = d3.arc()
    .outerRadius(chartWidth / 2 - 10)
    .innerRadius(0);

var colours = ['#F00', '#000', '#000', '#000', '#000', '#000', '#000', '#000', '#000'];

module.exports = function(pieData, outputLocation) {
    if (!pieData) pieData = [12, 31];
    if (!outputLocation) outputLocation = 'test.svg';
    const window = (new JSDOM(`<html><head></head><body></body></html>`, { pretendToBeVisual: true })).window;

    window.d3 = d3.select(window.document); //get d3 into the dom

    //do yr normal d3 stuff
    var svg = window.d3.select('body')
        .append('div').attr('class', 'container') //make a container div to ease the saving process
        .append('svg')
        .attr('xmlns', 'http://www.w3.org/2000/svg')
        .attr('width', 'chartWidth')
        .attr('height', 'chartHeight')
        .append('g')
        .attr('transform', 'translate(' + chartWidth / 2 + ',' + chartWidth / 2 + ')');

    svg.selectAll('.arc')
        .data(d3.pie()(pieData))
        .enter()
        .append('path')
        .attr('class', 'arc')
        .attr('d', arc)
        .attr('fill', function(d, i) {
                return colours[i];
            })
        .attr('stroke', '#fff');

    //write out the children of the container div
    fs.writeFileSync(outputLocation, window.d3.select('.container').html()) //using sync to keep the code simple
}

if (require.main === module) {
    module.exports();
}

@diogobaltazar
Copy link

thanks @dam1r89!

@g-gundam
Copy link

thanks from me too @dam1r89 .

@NikitaIT
Copy link

And transitions should starts from default:

+     .attr("d", (d) => arc(d))
      .transition()
      .duration(1000)
      .attrTween("d", (d) => ... (t) => arc(interpolate(t)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment