block by vicapow 758fce6aa4c5195d24be

An example of creating a PNG from an SVG in D3.

Full Screen

This is an example of creating a PNG from an SVG. (You should notice that you’re able to right click on the last image and save it as a PNG image.) It has been Tested in Firefox and Chrome but doesn’t work in Safari as of 2014-07-20.

Normally, you’ll create your SVG in D3 but to make the example a bit more readable, the SVG is already placed in the document. There are a few important points. Namely:

  1. All the styles of the SVG need to be self contained in side of the <defs> tags. (These styles should be escaped using the <![[CDATA[ ... ]] tag.)
  2. The SVG needs to have the proper namespaces and document types.
  3. The SVG needs to be saved to an image, then read from an canvas element, then saved to an image again.

Note: Portions of this demo where taken from The New York Times’ excellent Crowbar SVG extractor.

index.html

<!DOCTYPE html>
<html>
  <head>
  <body>
  <svg width="100" height="100" xmlns="//www.w3.org/2000/svg"
    xmlns:xlink="//www.w3.org/1999/xlink">
    <defs>
      <style type="text/css">
        circle { fill: red; }
      </style>
    </defs>
  <circle r="30" cx="50" cy="50"></circle>
</svg>
<script src="//d3js.org/d3.v3.js" charset="utf-8"></script>
<script>

var doctype = '<?xml version="1.0" standalone="no"?>'
  + '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "//www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">';

// serialize our SVG XML to a string.
var source = (new XMLSerializer()).serializeToString(d3.select('svg').node());

// create a file blob of our SVG.
var blob = new Blob([ doctype + source], { type: 'image/svg+xml;charset=utf-8' });

var url = window.URL.createObjectURL(blob);

// Put the svg into an image tag so that the Canvas element can read it in.
var img = d3.select('body').append('img')
 .attr('width', 100)
 .attr('height', 100)
 .node();


img.onload = function(){
  // Now that the image has loaded, put the image into a canvas element.
  var canvas = d3.select('body').append('canvas').node();
  canvas.width = 100;
  canvas.height = 100;
  var ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0);
  var canvasUrl = canvas.toDataURL("image/png");
  var img2 = d3.select('body').append('img')
    .attr('width', 100)
    .attr('height', 100)
    .node();
  // this is now the base64 encoded version of our PNG! you could optionally 
  // redirect the user to download the PNG by sending them to the url with 
  // `window.location.href= canvasUrl`.
  img2.src = canvasUrl; 
}
// start loading the image.
img.src = url;


</script>
</body>
</html>