5

Goal - using the client-side:

Convert a dynamic SVG drawing (created using d3js) to a downloadable PNG image and works using Internet Explorer.

Accomplished:

Achieved in Chrome, no problem. Once I have the PNG DataURI it is easily converted to a downloadable PNG blob.

Unfortunately in IE running the same code produces a SecurityException, it fails when I try to convert the canvas to the PNG DataURI (canvas.toDataURL).

Apparently this is an active IE BUG and I've found others on StackExchange with the same issue. I believe it is related to the CORS restrictions applied on images that originate from other domains (and are drawn in a canvas), but my SVG has originated from the local page.

Thoughts

Wondering if the cause is related to the way I was generating the initial DataURI (data:image/svg+xml) for the SVG drawing that is rendered by the IMG element.

I have tried two alternatives to produce the image/svg+xml, base64 and charset=utf8, but they have not overcome the issue encountered. So wondering if it is the content of the SVG, presently there are no images within the SVG drawing.

Code for reference:

var rawSvg = new XMLSerializer().serializeToString(svgElement);

var img3 = new Image();
document.body.appendChild(img3);
var canv = document.createElement("canvas");
var canv_ctx = canv.getContext("2d");

img3.onload = function () {
   //-- Image has loaded using the native data:image/svg+xml 
   canv_ctx.drawImage(this, 0, 0);

   //-- IE Will throw a Security Exception here...
   console.log(canv.toDataURL("image/png")); 
};

img3.src = "data:image/svg+xml;base64," + btoa(rawSvg);
//-- Or utf8
//img3.src = "data:image/svg+xml;charset=utf8," + encodeURIComponent(rawSvg);

UPDATE:

Tested Canvg's extension to 2d context "drawSvg(...)" which draws onto the canvas. This overcomes the SecurityException when calling toDataURL on the canvas element, however the draw function is not accurate enough for text rendering and placement. So I am still in need of a solution.

See example screenshot, left correct rending using native drawImage and right the incorrect rendering using Canvg's drawSvg

Code using Canvg - NB: You'll need to reference the JS

var canvas = document.createElement("canvas"),
    cctx = canvas.getContext("2d");
var rawSvg = new XMLSerializer().serializeToString(svgClone.node());
canvas.width = svgWidth;
canvas.height = svgHeight;
//cctx.drawImage(this, 0, 0);
//-- Use Canvg's extension to canvasContext
cctx.drawSvg(rawSvg);
//-- This Works on IE - not accurate though
var dataURL = canvas.toDataURL();
Nicholas
  • 572
  • 6
  • 17
  • Depending on the complexity of the SVG created by d3 you can use [canvg](https://github.com/gabelerner/canvg) to convert the svg to canvas drawing commands. Then the cross-domain restrictions no longer apply. – markE Mar 31 '16 at 01:42
  • Yes it's a security restriction that were applied on IE"png" Note that the same restriction does apply on latest safari's version when you do draw an svg containing a `` element. Ps: this restriction doesn't apply anymore on Edge so I don't think the bug you linked to (which was a feature and not a bug btw) will ever be fixed. – Kaiido Mar 31 '16 at 01:53
  • 1
    @markE I just did a test on their JS fiddle playground and if I use their drawimage on the canvas element then I can produce a DataURI instance on the Canvas. That is great! Thanks, I'll post some code once I have verified it works on my machine. – Nicholas Mar 31 '16 at 02:00
  • @Kaiido cheers, didn't realise this worked on Edge. I have done a quick test using canvg as per MarkE's suggestion to draw onto the canvas and this seems to allow export to PNG. – Nicholas Mar 31 '16 at 02:02
  • @Nicholas, yes, but you'll also face a lot of restrictions / bugs with canvg, if you do use some more advanced svg features (text rendering, filters ...). But definitely it can be an option for IE. – Kaiido Mar 31 '16 at 02:08
  • @Kaiido no you are right, not good enough. The SecurityException is a BUG or IE is lazy at validating the internals of the SVG and marks it tainted from the start. – Nicholas Mar 31 '16 at 02:45
  • 2
    @Nicholas, I'm afraid we gave you the only 3 solutions you have. Fix canvg library , write your own svg to canvas drawing commands library, ask your user to right click the svg "save as.." "png" – Kaiido Mar 31 '16 at 03:05

0 Answers0