Skip to content

Instantly share code, notes, and snippets.

@vicapow
Last active December 17, 2019 11:15
Show Gist options
  • Star 14 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save vicapow/758fce6aa4c5195d24be to your computer and use it in GitHub Desktop.
Save vicapow/758fce6aa4c5195d24be to your computer and use it in GitHub Desktop.
An example of creating a PNG from an SVG in D3.

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.

<!DOCTYPE html>
<html>
<head>
<body>
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://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="http://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" "http://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>
@amergin
Copy link

amergin commented Jul 12, 2015

Should the new Blob technique work in Safari? What I'm experiencing is that it works in FF/Chrome but not in Safari. By using the technique described here it'll work in Safari as well.

Edit: should've read the readme :D. Yep, you were already aware of this.

@suhelroorkee
Copy link

Hi can you please elaborate how we can save this into our customize directory ?

@capan
Copy link

capan commented Dec 17, 2019

when I try to implement this piece of code in React.js, img.onload is never called.

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