Sleenee
Sleenee

Reputation: 594

d3.js download graph as svg image

I have been lookig around for a way to download the generated svg from d3.js and I either end up with phantom.js which seems kinda overkill (or at least intimidating given the "simplicity" of the problem) or svg-crowbar.js which is apparently only for chrome (I need firefox).

I also found the following code:

//Encode the SVG
var serializer = new XMLSerializer();
var xmlString = serializer.serializeToString(d3.select('svg').node());
var imgData = 'data:image/svg+xml;base64,' + btoa(xmlString);
//Use the download attribute (or a shim) to provide a link
<a href="'+imgData+'" download="download">Download</a>

on https://groups.google.com/forum/#!topic/d3-js/RnORDkLeS-Q

Which should download the svg (if I could get it to work). I was thinking that instead of supplying a download button, clicking a certain svg-element should also do? I currently have the following code but it doesn't work:

 var svg = d3.select(elementid).append("svg")
                        .attr("width", 500)
                        .attr("height", 500)
                        .append("g")

            var serializer = new XMLSerializer();
            var xmlString = serializer.serializeToString(d3.select('svg').node());
            var imgData = 'data:image/svg+xml;base64,' + btoa(xmlString);
            //Use the download attribute (or a shim) to provide a link

                    svg.append("rect")
                            .attr("x", 20)
                            .attr("y", 20)
                            .attr("width", 130)
                            .attr("height", 160)
                            .attr("fill", "red")
                            .attr("id", "rectLabel")
                            .attr('xlink:href',imgData);

the svg only draws the rectangle should allow you to download the svg (with the rectangle) as an .svg file when the rectangle is pressed. I don't know if I am on the right track here.

I am very new to d3.js but basically I am looking for a possible fix / alternative for client side d3.js svg download in Firefox. Preferably I would have the download "button" as part of the svg.

thanks in advance!

Upvotes: 5

Views: 9407

Answers (3)

Alex Lenail
Alex Lenail

Reputation: 14440

I found this block to have the best solution.

  • Markup:

    <a id="download" href="#">Download SVG</button>
    
  • javasript:

    d3.select("#download").on("click", function() {
      d3.select(this)
        .attr("href", 'data:application/octet-stream;base64,' + btoa(d3.select("#line").html()))
        .attr("download", "viz.svg") 
    })
    

Upvotes: 2

maia
maia

Reputation: 4360

I've modified the svg-crowbar script to be a function called downloadSVG() that can be called from within your script. The function downloads SVG(s) on the webpage. The function can be found at: https://bitbucket.org/mas29/public_resources/raw/b9bafa002053b4609bd5186010d19e959cba33d4/scripts/js/svg_download/downloadSVG.js.

Let's say you have a button that, when pushed, should download the SVG(s). Just tack on the downloadSVG() as part of the "click" function, like so:

d3.select("body").append("button")
        .attr("type","button")
        .attr("class", "downloadButton")
        .text("Download SVG")
        .on("click", function() {
            // download the svg
            downloadSVG();
        });

Upvotes: 2

Sleenee
Sleenee

Reputation: 594

Ok , I have settled with just allowing the specification of a button (with downloadID) and have added this in the code after creating the svg.

            if (p.graph.svg.downloadID != undefined){
                var serializer = new XMLSerializer();
                var xmlString = serializer.serializeToString(d3.select('svg').node());
                var imgData = 'data:image/svg+xml;base64,' + btoa(xmlString);

                function writeDownloadLink(){
                    var html = d3.select(elementid).select("svg")
                            .attr("title", "svg_title")
                            .attr("version", 1.1)
                            .attr("xmlns", "http://www.w3.org/2000/svg")
                            .node().parentNode.innerHTML;  

                    d3.select(this)
                            .attr("href-lang", "image/svg+xml")
                            .attr("href", "data:image/svg+xml;base64,\n" + btoa(unescape(encodeURIComponent(html))))
                };

                var idselector = "#"+p.graph.svg.downloadID;

                d3.select(idselector)
                        .on("mouseover", writeDownloadLink);

            } 

Not what I had in mind at first but works for me.

Upvotes: 6

Related Questions