Problem saving as png a SVG generated by Raphael JS in a canvas

10,405

Solution 1

canvg accepts the SVG data a file path or a single-line string

but in your code, your are passing the html content of the div #ec as

canvg('canvas', svg, {renderCallback: saveDaPicture, ignoreMouse: true, ignoreAnimation: true});

Both jQuery's $.html() and DOM's innerHTML methods return the HTML content of an element as is, so most probably in multiple lines.

canvg interprets this multi-line html content as a file path,

<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="512"> 

and tries to fetch the data from the malformed url.

So the SVG to Canvas conversion process failed and that's the reason you are not getting the image as expect.

Here is a updated version that should work,

function saveDaPicture(){
    var img = document.getElementById('canvas').toDataURL("image/png");
    $('body').append('<img src="'+img+'"/>');
}

$('#save').click(function(){
    var svg = $('#ec').html().replace(/>\s+/g, ">").replace(/\s+</g, "<");
                             // strips off all spaces between tags
    //alert(svg);
    canvg('canvas', svg, {renderCallback: saveDaPicture, ignoreMouse: true, ignoreAnimation: true});
});

Solution 2

svgfix.js will solve this errors. take a look at this blog post Export Raphael Graphic to Image

Solution 3

I worked with SVG - Edit and generated SVG images, what we did was install ImageMagic on the server (you probably have it installed already).

Once installed you only need to do execute a command like "convert foo.svg foo.png" in the terminal. If you are using php then you can do:

shell_exec("convert image.svg image.png");

In php and it's done.

Share:
10,405
Shikiryu
Author by

Shikiryu

Designer &amp; Developer You can watch my website and read my resume

Updated on June 04, 2022

Comments

  • Shikiryu
    Shikiryu about 2 years

    I'm trying to convert a SVG generated by Raphael JS (and the user, since you can drag and rotate the images). I followed this Convert SVG to image (JPEG, PNG, etc.) in the browser but still can't get it.

    It must be easy but I can't put my finger on what I get wrong.

    I got my svg in a div with #ec as id and the canvas's one is #canvas.

    function saveDaPicture(){
        var img = document.getElementById('canvas').toDataURL("image/png");
        $('body').append('<img src="'+img+'"/>');
    }
    $('#save').click(function(){
        var svg = $('#ec').html();
        alert(svg);
        canvg('canvas', svg, {renderCallback: saveDaPicture(), ignoreMouse: true, ignoreAnimation: true});
    });
    

    The alert gives me :

    <svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="512">
    <desc>Created with Raphael</desc>
    <defs></defs>
    <image x="0" y="0" width="300" height="512" preserveAspectRatio="none" href="imageurl.jpg"></image>
    <rect x="168" y="275" width="52" height="70" r="0" rx="0" ry="0" fill="none" stroke="#000" stroke-dasharray="8,3" transform="rotate(21.91207728 194 310)" style="opacity: 1; display: none; " opacity="1"></rect>
    <circle cx="50" cy="50" r="50" fill="none" stroke="#000"></circle>
    <image x="358" y="10" width="39" height="138" preserveAspectRatio="none" href="imageurl2.png" style="cursor: move; "></image>
    <image x="397" y="10" width="99" height="153" preserveAspectRatio="none" href="imageurl3.png" style="cursor: move; "></image>
    <image x="184" y="286" width="10" height="10" preserveAspectRatio="none" href="imageurl4.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
    <image x="204" y="286" width="10" height="10" preserveAspectRatio="none" href="imageurl5.png" style="cursor: pointer; opacity: 1; display: none; " opacity="1"></image>
    <image x="170" y="277" width="48" height="66" preserveAspectRatio="none" href="imageurl6.png" style="cursor: move; opacity: 1; " r="50" opacity="1" transform="rotate(21.91207728 194 310)"></image>
    </svg>
    

    which is the xml of the svg and if I believe canvg documentation, it's good.

    Anyway, with this code, the variable img, which should have the converted image data, got the data of an empty png with the dimensions of the svg.

    The only thing I guess is that the svg generated by Raphael JS is not well formated for canvg (like, href of image should be xlink:href if I follow the W3C recommandations )

    Anyone got an idea on this problem ? :D

  • Shikiryu
    Shikiryu over 13 years
    Unfortunatly, I don't have ImageMagick installed on my server which is shared so I can't install it either. Nonetheless, it's quite a nice hint if someone got the same problem as mine. +1
  • Shikiryu
    Shikiryu over 13 years
    It may be this, now that you point it out. Isn't there a way in JS to make a multiline into only one line?
  • Livingston Samuel
    Livingston Samuel over 13 years
    of course you can convert multiline to singleline, i'm updating my answer
  • Josh Darnell
    Josh Darnell almost 12 years
    Hi Ignacio! Here on Stack Overflow, link only answers are not considered answers. Unless you flesh it out with some code, your answer is in danger of being deleted per the faq section on deletion, especially "Answers that do not fundamentally answer the question may be removed. This includes answers that are … barely more than a link to an external site"
  • Homer6
    Homer6 over 11 years
    which is a shame, because this is the best answer
  • Terry
    Terry about 11 years
    Just an FYI, this requires a <canvas> element which is not generated by Raphael and does not work in older browsers. There are certainly workarounds but keep that in mind.