4

I'm attempting to create an image from a svg on a page. However, I was unable to get the svgToImage() function working on google chrome. I switched browsers to firefox, and everything generated without any issues. Firefox seems to generate a different base64 representation of the svg, and when this version is used in google chrome, it works, but the function still fails to create an image.

Looking into some of the debug logs, it seems as though firefox turns the svg element from <svg> into <a0:svg>. Is this why this code is working in firefox? If so, is it due to an incorrect namespace that firefox fixes and chrome ignores?

I've posted the snippet I've been using to test. On chrome, one should see two back boxes, and then a broken image. On firefox, there should be three black boxes.

function svgToImage(target) {
    // Works in firefox 
    // https://gist.github.com/Caged/4649511
    var svg = document.getElementById(target);
    var xml = new XMLSerializer().serializeToString(svg);
    var data = 'data:image/svg+xml;base64,' + btoa(xml);
    var image = new Image(); 
    image.setAttribute('src', data); 
    document.body.appendChild(image);
}

//Generate another svg 
svgToImage('aSVG');
<svg width="100" height="100" id="aSVG" xmlns="http://www,w3.org/2000/svg">
 <rect id="someId" x="70" y="70" width="15" height="20" fill="#000" rx="5" ry="5" />
</svg>

<!-- generated from firefox --> 
<img src="data:image/svg+xml;base64,PGEwOnN2ZyB4bWxuczphMD0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zPSJodHRwOi8vd3d3LHczLm9yZy8yMDAwL3N2ZyIgaWQ9ImFTVkciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIj4KCQkJPGEwOnJlY3Qgcnk9IjUiIHJ4PSI1IiBmaWxsPSIjMDAwIiBoZWlnaHQ9IjIwIiB3aWR0aD0iMTUiIHk9IjcwIiB4PSI3MCIgaWQ9InNvbWVJZCIvPgoJCTwvYTA6c3ZnPg==" ></img>

1 Answers1

5

It failed because you had a comma in your xmlns attribute instead of a dot.

When embedding SVG inline in HTML, you don't need the xmlns, so you can remove it.

function svgToImage(target) {
    // Works in firefox 
    // https://gist.github.com/Caged/4649511
    var svg = document.getElementById(target);
    var xml = new XMLSerializer().serializeToString(svg);
    var data = 'data:image/svg+xml;base64,' + btoa(xml);
    var image = new Image(); 
    image.setAttribute('src', data); 
    document.body.appendChild(image);
}

//Generate another svg 
svgToImage('aSVG');
<svg width="100" height="100" id="aSVG">
 <rect id="someId" x="70" y="70" width="15" height="20" fill="#000" rx="5" ry="5" />
</svg>

<!-- generated from firefox --> 
<img src="data:image/svg+xml;base64,PGEwOnN2ZyB4bWxuczphMD0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zPSJodHRwOi8vd3d3LHczLm9yZy8yMDAwL3N2ZyIgaWQ9ImFTVkciIGhlaWdodD0iMTAwIiB3aWR0aD0iMTAwIj4KCQkJPGEwOnJlY3Qgcnk9IjUiIHJ4PSI1IiBmaWxsPSIjMDAwIiBoZWlnaHQ9IjIwIiB3aWR0aD0iMTUiIHk9IjcwIiB4PSI3MCIgaWQ9InNvbWVJZCIvPgoJCTwvYTA6c3ZnPg==" ></img>
Paul LeBeau
  • 97,474
  • 9
  • 154
  • 181
  • The bug being that it accepts a bad namespace declaration? Weirdly, in a standalone fiddle Chrome bahaves the same as FF. It seems there is something about the S.O. snippet that forces the failure. http://jsfiddle.net/k7en0nxs/ – Paul LeBeau Oct 09 '15 at 12:36
  • https://bugzilla.mozilla.org/show_bug.cgi?id=1213275 https://code.google.com/p/chromium/issues/detail?id=541575 – Paul LeBeau Oct 09 '15 at 13:28
  • Ahh, in fact xmlns should be ignored in html by the html parser. serializeToString should then create output with the right namespace because the html parser has guessed it from the context. In fact, the xmlns attribute is not required at all and is best left out (it's an XML thing, not an html thing). – Robert Longson Oct 09 '15 at 13:34