How to convert/save d3.js graph to pdf/jpeg

69,532

Solution 1

As pointed out by @Premasagar in this comment on this question Convert SVG to image (JPEG, PNG, etc.) in the browser

If the borwser supports both SVG and canvas you can use this technique https://svgopen.org/2010/papers/62-From_SVG_to_Canvas_and_Back/index.html

function importSVG(sourceSVG, targetCanvas) {
    // https://developer.mozilla.org/en/XMLSerializer
    svg_xml = (new XMLSerializer()).serializeToString(sourceSVG);
    var ctx = targetCanvas.getContext('2d');

    // this is just a JavaScript (HTML) image
    var img = new Image();
    // http://en.wikipedia.org/wiki/SVG#Native_support
    // https://developer.mozilla.org/en/DOM/window.btoa
    img.src = "data:image/svg+xml;base64," + btoa(svg_xml);

    img.onload = function() {
        // after this, Canvas’ origin-clean is DIRTY
        ctx.drawImage(img, 0, 0);
    }
}

Solution 2

To display your svg within a canvas, you first have to convert it using a parser/renderer utility such as http://code.google.com/p/canvg/

(code adapted from: Convert SVG to image (JPEG, PNG, etc.) in the browser, not tested)

// the canvg call that takes the svg xml and converts it to a canvas
canvg('canvas', $("#my-svg").html());

// the canvas calls to output a png
var canvas = document.getElementById("canvas");
var img = canvas.toDataURL("image/png");

Solution 3

Just a heads up that I turned this concept into a small JavaScript library: https://github.com/krunkosaurus/simg

It simply converts any SVG to an image to swap out or trigger a download. Idea taken from here: http://techslides.com/save-svg-as-an-image/

Solution 4

The Simg library created and suggest by Mauvis Ledford above worked great for allowing my svg charts created with Dimple to be downloaded.

I did however need to change one aspect of the code to make it work. Inside of the toString() prototype, inside the forEach loop (line 37), if you change "svg.setAttribute(..)" to "svg[0].setAttribute" it will alleviate the "setAttribute(..) is not a function" error. Similarly the same needs to be done right below in the return statement, appending "[0]" after svg (line 39).

I also had to manually edit the "canvas.width" and "canvas.height" (lines 48 & 49) assignments in the toCanvas() prototype, in order to make the downloaded image a more correct size (it was previously just downloading a static 300x150 square in the top left corner of the chart).

Share:
69,532
Moein
Author by

Moein

Updated on March 06, 2020

Comments

  • Moein
    Moein about 4 years

    I'm working on a client-side/javascript function to save or convert an existing D3-SVG graph into a file. I've searched a lot and found some recommendations, mainly using canvas.toDataURL().

    I have no <canvas> in my page, and instead using:d3.select("body").append("svg").... I've also tried to append the SVG to the <canvas> but nothing happens.

    Could you please help me to resolve this exception:

    Uncaught TypeError: Object #<SVGSVGElement> has no method 'toDataURL' 
    

    Thank you