1

I have an SVG I need to 'convert' to a .png image, dynamically through JavaScript. The way this is done is the SVG is drawn into a virtual HTML5 canvas element, then converted via the toDataURL method into a data URI. The code is as follows:

HTML:

<div id="something" data-svg="<svg viewBox='0 0 105 93' xmlns='http://www.w3.org/2000/svg'><path d='M66,0h39v93zM38,0h-38v93zM52,35l25,58h-16l-8-18h-18z' fill='#ED1C24'/></svg>">

JS (using jQuery):

$(function() {

  var svgData = $('#something').data('svg');
  var imageUrl = svgToImageURL(svgData);


  function svgToImageURL(svgString){
    var canvas = document.createElement("canvas");
    canvas.width = 260;
    canvas.height = 260;
    var ctx = canvas.getContext("2d");
    var DOMURL = self.URL || self.webkitURL || self;
    var img = new Image();
    var svg = new Blob([svgString], {type: "image/svg+xml;charset=utf-8"});
    var url = DOMURL.createObjectURL(svg);

    img.onload = function() {
      ctx.drawImage(img, 0, 0);
      var png = canvas.toDataURL("image/png");
      document.getElementById('something').innerHTML = '<img src="'+png+'"/>';
      DOMURL.revokeObjectURL(png);
    };

    img.src = url;
  }

A fiddle can be seen here to demonstrate: https://jsfiddle.net/hejjgu7b/. It should render out the Adobe logo as an image in the page.

It works fine in Chrome and Edge, but in Firefox the image is always empty. It looks like the data URI is malformed in some way, as it's much shorter than that rendered in Chrome/Edge.

I wondered if anyone could see why this is happening, and how to get Firefox to render the correct data URI?

Many thanks.

Dan
  • 5,836
  • 22
  • 86
  • 140
  • 1
    Looks rather like an issue with drawing the SVG content onto the canvas in the first place. (Put the canvas element into the HTML instead of creating it in script only, then you’ll see that other browsers show the SVG image, whereas in Firefox the canvas itself stays blank.) – CBroe Jan 11 '17 at 13:22
  • Thanks @CBroe, that's prompted a different line of enquiry - please see my answer below. – Dan Jan 11 '17 at 13:47

2 Answers2

3

Why so complicated? You don´t need to render the svg inside a canvas. You can simply encode it to base 64 using btoa()

btoa("<svg>...");

Then, you simply add the data-url prefix.

"data:image/svg+xml;base64," + btoa("<svg>...");
Franz Deschler
  • 2,456
  • 5
  • 25
  • 39
  • 1
    Thanks for this answer, but it only results in a uri-encoded SVG, not a `.png`. Although the code above eludes to the fact it should output a png, I've amended the question to make this clearer. – Dan Jan 11 '17 at 13:39
3

It seems, according to this post, that there's a bug whereby Firefox will not render SVGs to canvas unless the SVG has (non-percentage-based) width and height attributes.

One of the challenges in this project is that our SVGs will not have such attributes, but we may be able to overcome that. This issue itself is fixed now by adding dimensions (<svg width='105' height='93'...>), as per the updated fiddle: https://jsfiddle.net/hejjgu7b/2/

Community
  • 1
  • 1
Dan
  • 5,836
  • 22
  • 86
  • 140