Sex, drugs and sausage rolls

Tech and Life… as seen by Tallmaris (il Gran Maestro)

Showing an SVG as image

Hello fellow developers!

Recently I have been using Raphaël a lot to generate SVGs on my page. It is a great tool and I invite you to visit the page to see a few demo of its capabilities.

One question that my clients were asking was if they could save the SVGs generated as images on his machine, by the usual right-click -> save we are used to. Normally SVGs don’t have this functionality; moreover, since we are generating SVGs dynamically on the client, we don’t have the option of using an tag which points to a svg file on the server.

After a bit of digging I found a solution in using data URI (you can read a bit more about it here). What is more, is that everything is being created on the client itself and it’s only a few lines of javascript code.

Let’s assume you have this HTML:

<div id="paper" style="text-align: center;"></div>

And inside that div you put your SVG; maybe you created it with Raphaël:

var raphael = Raphael('paper', 900, 700);
// ... actual SVG creation code not shown ...

After you finish drawing you can call the following function, passing the id of the parent div (‘paper’ in our case):

function encodeSvgAsImg(divId) {
$("svg desc").remove();
if ($("#"+divId).html().indexOf('xmlns') === -1) {
$("svg").attr("xmlns", "");
var svg = $("#" + divId).html();
var encoded = window.btoa(svg);
$("#" + divId)
.append($("<img id='" + divId +
"' src='data:image/svg+xml;charset=utf8;base64," + encoded +
"' alt='wheel.svg' />"));

Let’s go through the code.

First we remove the desc tag from the svg; this is added automatically by Raphaël and it is something like this:

<desc style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
    Created with Raphaël 2.1.2

I remove it simply because the little ë is a unicode character and it causes problems to some browsers when encoding and decoding in base64.

Next is a quick hack to avoid a problem with IE. Basically in Internet Explorer the xmlns attribute is added to the svg tag automatically and it is actually visible in the source rather than being added behind the scene. The simple fact that Raphaël too adds the attribute means that in IE you end up with two of them. This may not be a problem when putting the svg on the page but when using it with the data URI it will not work.

To solve this I remove the xmlns attribute; this will effectively remove it only from non-IE browsers, so in the next line we test if the actual html still contains the “xmlns” string and if it doesn’t it means we are in another browser and we need to re-add it (or again, it won’t work).

The rest is simple preparation, we get the html (basically the full svg tag) and we encode it in base 64, then we clear the parent div and append an img tag holding the same svg.

You should be able to see an example in the fiddle below; it is the typical Raphaël tiger demo showing as an image; you can try right clicking and saving to see it working.

That’s all! Now your clients can happily save your fancy generated SVG charts and put them in their presentations or documents. Happy coding!

, , ,

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.