How to draw an inline svg (in DOM) to a canvas?

Well, I need some help about convert .svg file/image to .png file/image...

I have a .svg image displayed on my page. It is saved on my server (as a .png file). I need to convert it to a .png file on demand (on click on a button) and save the .png file on the server (I will do this with an .ajax request).

But the problem is the conversion.

I read many things about the html5 Canvas, which can probably help doing what I need to do now, but I can't find any clear solution to my problem, and, tbh, I do not understand everything I found... So I need some clear advices/help about the way I have to do it.

Here is the "html idea" template :

<html>
    <body>
        <svg id="mySvg" width="300px" height="300px">
            <!-- my svg data -->
        </svg>
        <label id="button">Click to convert</label>
        <canvas id="myCanvas"></canvas>
    </body>
</html>

and some js :

<script>
    $("body").on("click","#button",function(){
        var svgText = $("#myViewer").outerHTML;
        var myCanvas = document.getElementById("canvas");
        var ctxt = myCanvas.getContext("2d");
    });
</script>

Then, I need to draw the svg into the Canvas, get back the base64 data, and save it in a .png file on my server... but... how? I read about so many different solutions that I'm actually... lost... I'm working on a jsfiddle, but I'm actually... nowhere... http://jsfiddle.net/xfh7nctk/6/ ... Thanks for reading / help

Answers:

Answer

For inline SVG you'll need to:

  • Convert the SVG string to a Blob
  • Get an URL for the Blob
  • Create an image element and set the URL as src
  • When loaded (onload) you can draw the SVG as an image on canvas
  • Use toDataURL() to get the PNG file from canvas.

For example:

function drawInlineSVG(ctx, rawSVG, callback) {

    var svg = new Blob([rawSVG], {type:"image/svg+xml;charset=utf-8"}),
        domURL = self.URL || self.webkitURL || self,
        url = domURL.createObjectURL(svg),
        img = new Image;

    img.onload = function () {
        ctx.drawImage(this, 0, 0);     
        domURL.revokeObjectURL(url);
        callback(this);
    };

    img.src = url;
}

// usage:
drawInlineSVG(ctxt, svgText, function() {
    console.log(canvas.toDataURL());  // -> PNG data-uri
});

Of course, console.log here is just for example. Store/transfer the string instead here. (I would also recommend adding an onerror handler inside the method).

Also remember to set canvas size using either the width and height attributes, or from JavaScript using properties.

Answer

I come long after since some other question raised from this one because the accepted answer may produce undesirable behavior.

@K3N solution is almost right, but I would go against the use of svgElement.outerHTML.
Instead, one should prefer new XMLSerializer().serializeToString(svgElement).

Also, the use of blob and of the URL API is not necessary and a simple dataURI has more compatibility accross browsers.

So a complete version of this would be :

function drawInlineSVG(svgElement, ctx, callback){
  var svgURL = new XMLSerializer().serializeToString(svgElement);
  var img  = new Image();
  img.onload = function(){
    ctx.drawImage(this, 0,0);
    callback();
    }
  img.src = 'data:image/svg+xml; charset=utf8, '+encodeURIComponent(svgURL);
  }

//usage :
drawInlineSVG(document.querySelector('svg'), ctxt, function(){console.log(canvas.toDataURL())})

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.