Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 390
Sleenee Avatar asked Jun 06 '14 10:06

Sleenee


People also ask

Does D3 js use SVG?

We had briefly introduced Scalable Vector Graphics (SVG) in our web standards chapter. In this chapter, we will learn about creating SVG elements using D3. SVG provides different shapes like lines, rectangles, circles, ellipses etc.

Is D3 SVG or Canvas?

D3 charts are most often rendered using SVG, a retained mode graphics model, which is easy to use, but performance is limited. SVG charts can typically handle around 1,000 datapoints. Since D3 v4 you've also had the option to render charts using canvas, which is an immediate mode graphics model.

What does SVG stand for in D3?

SVG stands for Scalable Vector Graphics. SVG is an XML-based vector graphics format. It provides options to draw different shapes such as Lines, Rectangles, Circles, Ellipses, etc. Hence, designing visualizations with SVG gives you more power and flexibility.


2 Answers

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.

like image 156
Sleenee Avatar answered Oct 26 '22 15:10

Sleenee


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();
        });
like image 34
maia Avatar answered Oct 26 '22 15:10

maia