Skip to content

Instantly share code, notes, and snippets.

@gustavohenke
Created February 18, 2014 15:27
Show Gist options
  • Save gustavohenke/9073132 to your computer and use it in GitHub Desktop.
Save gustavohenke/9073132 to your computer and use it in GitHub Desktop.
SVG to PNG
var svg = document.querySelector( "svg" );
var svgData = new XMLSerializer().serializeToString( svg );
var canvas = document.createElement( "canvas" );
var ctx = canvas.getContext( "2d" );
var img = document.createElement( "img" );
img.setAttribute( "src", "data:image/svg+xml;base64," + btoa( svgData ) );
img.onload = function() {
ctx.drawImage( img, 0, 0 );
// Now is done
console.log( canvas.toDataURL( "image/png" ) );
};
@shreyashah9
Copy link

My onload function is not getting called here and even the image is not getting displayed..please suggest an option

@Bogdan-Catalin
Copy link

Using this to draw a d3pie pie chart to the canvas just renders an empty object.
However, I can easily append img to a container in the document and it's loaded as a SVG resource with no problems.

Any idea why ?

Edit: Decided to use canvg and pass svgData to it instead of creating an img out of it and it works ! But I still don't understand why the original code didn't work...

@amit-rana
Copy link

converting svg to data url is working but when I try to render it to canvas it's not showing images that used in svg... any idea I have already add required attrs to svg

here is my code

 var html = d3.select("svg")
    .attr({
        'xmlns': 'http://www.w3.org/2000/svg',
        'xmlns:xmlns:xlink': 'http://www.w3.org/1999/xlink',
        version: '1.1'
    }) 
    .node().parentNode.innerHTML;

  var imgsrc = 'data:image/svg+xml;base64,'+ btoa(html);

  d3.select('canvas').attr('width',_canvasWidth).attr('height',_canvasHeight);
  var canvas = document.querySelector("canvas"),
      context = canvas.getContext("2d");

  var image = new Image;
  image.src = imgsrc;
  image.onload = function() {
  context.drawImage(image, 0, 0);

  var canvasdata = canvas.toDataURL("image/png");

  var pngimg = '<img src="'+canvasdata+'">'; 
  d3.select("#pngdataurl").html(pngimg);

  var a = document.createElement("a");
  a.download = "export_"+Date.now()+".png";
  a.href = canvasdata; 
  document.body.appendChild(a);
  a.click();
  };

@maciejjankowski
Copy link

IE11 (probably others too) have some issues with SVG namespaces - I don't know if it is the Raphael to blame or something else. One solution is to fix the namespaces yourself:

you will have some weird stuff like:

xmlns:NS1="" NS1:xmlns:xlink="http://www.w3.org/1999/xlink"

replace it with:

xmlns:xlink="http://www.w3.org/1999/xlink"

and fix the xlinks accordingly

@lukehorvat
Copy link

lukehorvat commented Jun 3, 2015

If your SVG styling isn't inline, you can use this package: https://github.com/lukehorvat/computed-style-to-inline-style

@goosehub
Copy link

@philfreo , I found your function useful, but it was still partially cut off, so as a hack, I did this to ensure it wasn't cut off. Won't work in all cases. Just a heads up that getBoundingClientRect() doesn't seem to always work.

            canvas.width = svgSize.width * 2;
            canvas.height = svgSize.height * 2;

By the way, this gist is a lifesaver!

@palawer
Copy link

palawer commented Oct 29, 2015

Here's what i'm using. Works fine in Chrome but not on Firefox... Any ideas?

function svg_to_png(container) {
    var wrapper = document.getElementById(container);
    var svg = wrapper.querySelector("svg");

    if (typeof window.XMLSerializer != "undefined") {
        var svgData = (new XMLSerializer()).serializeToString(svg);
    } else if (typeof svg.xml != "undefined") {
        var svgData = svg.xml;
    }

    var canvas = document.createElement("canvas");
    var svgSize = svg.getBoundingClientRect();
    canvas.width = svgSize.width;
    canvas.height = svgSize.height;
    var ctx = canvas.getContext("2d");

    var img = document.createElement("img");
    img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData))) );

    img.onload = function() {
        ctx.drawImage(img, 0, 0);
        var imgsrc = canvas.toDataURL("image/png");

        var a = document.createElement("a");
        a.download = container+".png";
        a.href = imgsrc;
        a.click();
    };
}

@kyptov
Copy link

kyptov commented Jan 7, 2016

@Guillemp
put your img.setAttribute(...) after img.onload

@zhangbg
Copy link

zhangbg commented Jan 28, 2016

@Guillemp
you should append in the body!

document.body.appendChild(a);

@jankovicsandras
Copy link

@abishekrsrikaanth "Is there a way to convert PNG to SVG?"
Yes, there is now: https://github.com/jankovicsandras/imagetracerjs

@toastal
Copy link

toastal commented Jan 8, 2017

Seems a little odd to base64 encode it.... I went with

var img = new Image()
img.src = "data:image/svg+xml;utf8," + svgData

@maneetgoyal
Copy link

@toastal Using utf8 didn't seem to work. Did it work for you? I am Using Chrome.

@FALCON-084
Copy link

var svg = document.querySelector( "svg" );
var svgData = new XMLSerializer().serializeToString( svg );

var canvas = document.createElement( "canvas" );
var svgSize = svg.getBoundingClientRect();
canvas.width = svgSize.width;
canvas.height = svgSize.height;
var ctx = canvas.getContext( "2d" );

var img = document.createElement( "img" );
img.setAttribute( "src", "data:image/svg+xml;base64," + btoa( svgData ) );

img.onload = function() {
ctx.drawImage( img, 0, 0 );

// Now is done
console.log( canvas.toDataURL( "image/png" ) );

};

Worked with this code. but for some SVG files it is showing "NETWORK ERROR". Can u help?

@mehulchauhan31
Copy link

mehulchauhan31 commented Mar 26, 2018

When I convert SVG to PNG it only export graph plot not graph data to PNG .
Please Advice or suggest any solution.

@NorhanSamir
Copy link

I'm trying to export angular-d3-charts to PDF as an image but the chart is not complete the x-axis are hidden as it's not inline style is there any workaround to solve this ???

@linnabrown
Copy link

linnabrown commented Jun 24, 2020

You save my life!!!!!!!!!!!!!!!!!!!! @Guillemp This code works well! Thank you very much!

I used snap JS to draw svg, here what I do:

var s = Snap('#svg_id');
var svg = document.querySelector( "#svg_id" );
var svgData = new XMLSerializer().serializeToString( svg );
var canvas = document.createElement( "canvas" );
canvas.width = 1500;
canvas.height = 1450;
var ctx = canvas.getContext( "2d" );
var img = document.createElement( "img" );
img.setAttribute( "src", s.toDataURL());
console.log(s.toDataURL());
img.onload = function() {
	ctx.drawImage( img, 0, 0 );
	console.log( canvas.toDataURL( "image/png" ) );
	var imgsrc = canvas.toDataURL( "image/png" );
	var a = document.getElementById("download_png");
	a.download = "filename.png"
	a.href = imgsrc;
};

@morrisonmburu
Copy link

Here's what i'm using. Works fine in Chrome but not on Firefox... Any ideas?

function svg_to_png(container) {
    var wrapper = document.getElementById(container);
    var svg = wrapper.querySelector("svg");

    if (typeof window.XMLSerializer != "undefined") {
        var svgData = (new XMLSerializer()).serializeToString(svg);
    } else if (typeof svg.xml != "undefined") {
        var svgData = svg.xml;
    }

    var canvas = document.createElement("canvas");
    var svgSize = svg.getBoundingClientRect();
    canvas.width = svgSize.width;
    canvas.height = svgSize.height;
    var ctx = canvas.getContext("2d");

    var img = document.createElement("img");
    img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData))) );

    img.onload = function() {
        ctx.drawImage(img, 0, 0);
        var imgsrc = canvas.toDataURL("image/png");

        var a = document.createElement("a");
        a.download = container+".png";
        a.href = imgsrc;
        a.click();
    };
}

Thanks

var svg = document.querySelector( "svg" );
var svgData = new XMLSerializer().serializeToString( svg );

var canvas = document.createElement( "canvas" );
var svgSize = svg.getBoundingClientRect();
canvas.width = svgSize.width;
canvas.height = svgSize.height;
var ctx = canvas.getContext( "2d" );

var img = document.createElement( "img" );
img.setAttribute( "src", "data:image/svg+xml;base64," + btoa( svgData ) );

img.onload = function() {
ctx.drawImage( img, 0, 0 );

// Now is done
console.log( canvas.toDataURL( "image/png" ) );

};

Worked with this code. but for some SVG files it is showing "NETWORK ERROR". Can u help?

Here's what i'm using. Works fine in Chrome but not on Firefox... Any ideas?

function svg_to_png(container) {
    var wrapper = document.getElementById(container);
    var svg = wrapper.querySelector("svg");

    if (typeof window.XMLSerializer != "undefined") {
        var svgData = (new XMLSerializer()).serializeToString(svg);
    } else if (typeof svg.xml != "undefined") {
        var svgData = svg.xml;
    }

    var canvas = document.createElement("canvas");
    var svgSize = svg.getBoundingClientRect();
    canvas.width = svgSize.width;
    canvas.height = svgSize.height;
    var ctx = canvas.getContext("2d");

    var img = document.createElement("img");
    img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData))) );

    img.onload = function() {
        ctx.drawImage(img, 0, 0);
        var imgsrc = canvas.toDataURL("image/png");

        var a = document.createElement("a");
        a.download = container+".png";
        a.href = imgsrc;
        a.click();
    };
}

worked for me, thanks

@Tsutomu-miku
Copy link

if the svg element contains some tag, these code seems not work

@mehdi-repo
Copy link

sorry can somebody tell me what is container hier ? image Tag?
function svg_to_png(container) {
var wrapper = document.getElementById(container);
var svg = wrapper.querySelector("svg");

if (typeof window.XMLSerializer != "undefined") {
    var svgData = (new XMLSerializer()).serializeToString(svg);
} else if (typeof svg.xml != "undefined") {
    var svgData = svg.xml;
}

var canvas = document.createElement("canvas");
var svgSize = svg.getBoundingClientRect();
canvas.width = svgSize.width;
canvas.height = svgSize.height;
var ctx = canvas.getContext("2d");

var img = document.createElement("img");
img.setAttribute("src", "data:image/svg+xml;base64," + btoa(unescape(encodeURIComponent(svgData))) );

img.onload = function() {
    ctx.drawImage(img, 0, 0);
    var imgsrc = canvas.toDataURL("image/png");

    var a = document.createElement("a");
    a.download = container+".png";
    a.href = imgsrc;
    a.click();
};

}

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