downloading d3-generated svg

4,844 views
Skip to first unread message

Ken-ichi

unread,
May 23, 2011, 7:49:51 PM5/23/11
to d3-js
I'd like to offer viewers of my d3-generated SVG the option to
download the SVG as a file so they can edit it themselves, but I'm not
sure how to go about it. The best solution I could come up with is
kind of dumb: post the content of the SVG to a server and have the
server package the content into a file and offer it back with the
appropriate headers, triggering a download dialog. It just doesn't
seem like this should be necessary, though, since the data is already
sitting there in the client. Is there a pure JS way to do this?

-ken-ichi

Nelson Minar

unread,
May 23, 2011, 8:19:23 PM5/23/11
to d3...@googlegroups.com
I tried to do something similar last year and ended up using Downloadify, a tiny Flash shim to prepare the download.

In my case the XML was produced by Google Earth; it might be a bit different with SVG being in the DOM.

Things may have changed in the last year.

Chris Viau

unread,
Jun 1, 2011, 9:05:31 PM6/1/11
to d3...@googlegroups.com
For my personal use (like saving generated SVG to a file), I write the output on a textarea and copy-paste it in a local file. But if you want to write this file on the client file system with client-side code, you have to use some ActiveX for IE or a bit of Flash, a Java applet, etc. There is a Jquery plugin to write to a file called jQuery.twFile that can give you some ideas of the hacks it takes to be cross-platform and to overcome the limitations of Javascript. It's uglier than your first solution, which is the real one to use. 

Beau Gunderson

unread,
Jun 1, 2011, 9:19:04 PM6/1/11
to d3...@googlegroups.com
I had to do this at one point and settled on running node.js on the
server (with jsdom to simulate a browser environment); it worked well
to save out SVG files and turn them into PDFs.

I can dig up my test cases if anyone is interested.

Tim Triche, Jr.

unread,
Jun 1, 2011, 11:30:50 PM6/1/11
to d3...@googlegroups.com
I'm interested in the option for users to download a PDF, yes.  That would be quite useful.  Much obliged.
--

If people do not believe that mathematics is simple, it is only because they do not realize how complicated life is.


Chris Viau

unread,
Jun 2, 2011, 2:19:15 AM6/2/11
to d3...@googlegroups.com, ttr...@usc.edu
@Tim: You can use a php library like svg2pdf if you don't have a Node.js environment deployed on your server.

Beau Gunderson

unread,
Jun 6, 2011, 1:24:08 PM6/6/11
to d3...@googlegroups.com
Hey Tim, I tried to get my Protovis demo to work in Node with d3 and
it's currently failing--I'm still plugging away at it, though. :)

Tim Triche, Jr.

unread,
Jun 6, 2011, 1:29:51 PM6/6/11
to d3...@googlegroups.com
right on.  for the time being I'm just suggesting screen captures :-D

(I recognize that this makes me a Bad Human Being, but that's OK with me)

Chris Viau

unread,
Sep 19, 2011, 11:22:58 AM9/19/11
to d3...@googlegroups.com
Sorry for resurrecting an old thread, but here is an easy solution: http://bl.ocks.org/1209499

Nelson Minar

unread,
Sep 19, 2011, 12:44:20 PM9/19/11
to d3...@googlegroups.com
On Mon, Sep 19, 2011 at 8:22 AM, Chris Viau <christo...@gmail.com> wrote:
Sorry for resurrecting an old thread, but here is an easy solution: http://bl.ocks.org/1209499

Does this data: URL method really work for you? I just tested it and Firefox, Chrome, and Safari all just send you to a new page where (in most browsers) you can't even save it. Right click / download sort of works, but it's pretty awkward. And it doesn't seem to work at all in IE9.

Also from this old thread, the best method I've seen is still via a tiny Flash shim. Discussion here:


Ian Johnson

unread,
Sep 19, 2011, 12:51:52 PM9/19/11
to d3...@googlegroups.com
It works fine for me on chrome/ff/safari (Mac). I can save from the opened window or right click and save. Maybe if the link opened up with a title so the file would have a name when you went to save it would be nice.
--
Ian Johnson
Message has been deleted

Chris Viau

unread,
Sep 20, 2011, 11:15:50 AM9/20/11
to d3...@googlegroups.com
I updated my example to make it more obvious that you have to right-click and choose Save as. But you still have to enter the filename yourself in the download window and you can probably fight to make it work in IE. It is not the best solution but the original question was about a pure JS way to do it and it is the only one I know that don't require a shim or a round-trip to the server. 

Yar

unread,
Jun 25, 2012, 12:49:00 PM6/25/12
to d3...@googlegroups.com
yes, Beau, can you please post some examples of how you handled this?

Marc Fawzi

unread,
Jun 25, 2012, 2:40:09 PM6/25/12
to d3...@googlegroups.com, d3...@googlegroups.com
I used Downloadify (Actionscript) from JS, but if you can live with limited cross-browser support then the FileSystem API is the way to go (should work at least on Chrome)

To see a demo of SVG File saving using Downloadify, go to http://idibidiart.com in Firefox. The latest Firefox (12+) broke this "twitter art" app but you can still click on the Materialize link under each unicode drawing to see unicode-to-Canvas and Canvas-to-SVG and then Save As (for SVG filter effects -- set Shrink (vertical) then pick one of the SVG effects to see morphing of hard edged Unicode art to soft edged SVG -- all canvas/raster to SVG happens in JS)

if I was coding for webkit only I'd have used the FileSystem API for SVG saving. 

Sent from my iPhone

Yar

unread,
Jun 26, 2012, 12:12:47 AM6/26/12
to d3...@googlegroups.com
Thanks, marc.

The link says it will only work in firefox, and when i run it in firefox, it says i need OS/X or W7, and i'm running ubuntu. I'm hoping to find a more native method than downloadify, and avoid flash/actionscript.

I tried to use .innerHTML selection as Mike Bosock shows here. Looks super ideal, but i can't get it working.
https://groups.google.com/forum/?fromgroups#!topic/d3-js/aQSWnEDFxIc

From what I can tell of the filesystem API, is that it's 'sandboxed'. Security prevents any way to read/write to a user's home directory. I would like to be wrong here, because it does seem like the best option.

The other two options is a headless browser, or a round trip REST request.

jerome cukier

unread,
Jun 26, 2012, 6:54:33 AM6/26/12
to d3...@googlegroups.com
I've done this in one visualisation where I've used something like: 

d3.selectAll("#download-svg") .attr("href", "data:image/svg+xml;charset=utf-8;base64," + btoa(unescape(encodeURIComponent(
d3.selectAll("svg").attr("version", "1.1").attr("xmlns", "http://www.w3.org/2000/svg")
.node().parentNode.innerHTML)
)
)
)
.attr("download",filename);

Basically, it finds your svg, looks at the parent node (the containing div), takes its innerHTML, and encode it. The #download-svg refers to a button which, when clicked, downloads the svg as a file.
fyi this code is running at oecdfactblog.org/charter/charter.html.

marc fawzi

unread,
Jun 26, 2012, 4:18:32 PM6/26/12
to d3...@googlegroups.com
Yar,

The following demo actually works in Chrome (19+) for saving images
and text files so it should work for both Canvas and SVG

http://eligrey.com/demos/FileSaver.js/

from the demo site "The following examples demonstrate how it is
possible to generate and save any type of data right in the browser
using the W3C saveAs() FileSaver interface, without contacting any
servers."

hope this helps

Marc
--
Javascript/HTML5 >>
http://www.youtube.com/watch?v=Wd-d1p-c56U (Twitter Art Client --
Watch Me First)
http://www.youtube.com/watch?v=UX5jOvdLG8c (Canvas2Vector Effects)
http://www.youtube.com/watch?v=VLyLb3Otw5s (SVG Saving And Manipulation)

idom: http://idibidiart.github.com/idi.bidi.dom/ (DOM Anti-Templating)

Social >>
LinkedIn: http://www.linkedin.com/in/marcfawzi
Javascript blog: http://javacrypt.wordpress.com/
Thinking blog: http://evolvingtrends.wordpress.com/

Yar

unread,
Jun 26, 2012, 4:57:00 PM6/26/12
to d3...@googlegroups.com
Thanks marc!

I was having a really hard time wrapping my head around node().parentNode.innerHTML and DOM selection.

FileSaver.js suits my needs perfectly.

Marc Fawzi

unread,
Jun 27, 2012, 12:30:02 PM6/27/12
to d3...@googlegroups.com, d3...@googlegroups.com
That's great. 

The innerHTML stuff I believe is for getting the SVG markup content to be saved into the file. But I wasn't following the conversation earlier... So it might be for something else.

Sent from my iPhone

ar

unread,
Jun 28, 2012, 5:09:49 PM6/28/12
to d3...@googlegroups.com
I use the Web Developer Toolbar in Firefox and Chome.  View source, View generated source. Cut and Paste. It is very simple to use.

http://chrispederick.com/work/web-developer/help/

Vaughan Muller

unread,
Jun 10, 2013, 2:19:37 AM6/10/13
to d3...@googlegroups.com
Hey Chris,

Could you post some example code for outputting SVG code to a textarea?

Ian Johnson

unread,
Jun 10, 2013, 5:42:58 AM6/10/13
to d3...@googlegroups.com
here is a quick snippet that should help:
var el = d3.select(selector).node();
var string = new XMLSerializer().serializeToString(el);



--
You received this message because you are subscribed to the Google Groups "d3-js" group.
To unsubscribe from this group and stop receiving emails from it, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Ian Johnson - 周彦

Christophe Viau

unread,
Jun 10, 2013, 10:53:51 AM6/10/13
to d3...@googlegroups.com
This is an old answer. I now use a method closer to what Ian just proposed:

//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>

CHris
--

Travis White

unread,
Jun 25, 2013, 11:12:46 AM6/25/13
to d3...@googlegroups.com
Hello Chris,

Thank you it looks like your solution meets my requirements. However I'm having trouble getting it to work. I have a download link and when I pres it I am printing out the imgData variable.

My problem is I don't know how to return this data with a link..

Is your line : --- <a href="'+imgData+'" download="download">Download</a> --- a compltere solution or am I missing something?

Here is my code :
html
 <a href="'imgData'" download="download">Download</a>

javascript
     d3.select("#download")
                        .on("click", function(){

                    var serializer = new XMLSerializer();
                    var xmlString = serializer.serializeToString(d3.select('svg').node());
                    var imgData = 'data:image/svg+xml;base64,' + btoa(xmlString);
                    console.log(imgData)
                        });

Thank you

Christophe Viau

unread,
Jun 25, 2013, 12:43:17 PM6/25/13
to d3...@googlegroups.com
Can you share the code on Tributary/bl.ocks/gist/jsfiddle/plunker? What browser are you using?
Chris

Travis White

unread,
Jun 26, 2013, 5:21:18 AM6/26/13
to d3...@googlegroups.com
Sure..here it is : http://jsfiddle.net/travis94/DHHun/1/

I've definitely not im,plementing it right. I'm getting a 404 when I hit the download link. I'm using firefox on Mac.
Message has been deleted

mas29

unread,
Apr 13, 2016, 4:00:29 PM4/13/16
to d3-js
I've modified the svg-crowbar (https://github.com/NYTimes/svg-crowbar) script to be a function downloadSVG() that can be called from within your script. The function downloads the SVG(s) on the webpage. To use it, add ".on("click", function() { downloadSVG(); });" to your div button d3 code (assuming you have one). The downloadSVG() function is found at: https://bitbucket.org/mas29/public_resources/raw/b9bafa002053b4609bd5186010d19e959cba33d4/scripts/js/svg_download/downloadSVG.js.

On Monday, May 23, 2011 at 4:49:51 PM UTC-7, Ken-ichi wrote:
I'd like to offer viewers of my d3-generated SVG the option to
download the SVG as a file so they can edit it themselves, but I'm not
sure how to go about it.  The best solution I could come up with is
kind of dumb: post the content of the SVG to a server and have the
server package the content into a file and offer it back with the
appropriate headers, triggering a download dialog.  It just doesn't
seem like this should be necessary, though, since the data is already
sitting there in the client.  Is there a pure JS way to do this?

-ken-ichi

Jayson Harshbarger

unread,
Apr 22, 2016, 6:58:06 AM4/22/16
to d3-js
All,

I know this is an old thread, I only noticed because mas29 bumped it, but I created svgsaver (https://github.com/Hypercubed/svgsaver) some time ago as well as svgsaver-crowbar (https://github.com/Hypercubed/svgsaver-crowbar).  The difference between these and other solutions is that it convert CSS styles to inline before saving.  Also saves as PNG.

Jayson

Curran

unread,
Apr 23, 2016, 6:00:57 AM4/23/16
to d3-js
Hi Jayson,

SVGSaver is awesome!

I'm wondering, have you come across a way to preserve externally loaded fonts (e.g. Google Fonts) in the downloaded SVG? Ideally the shape of the text would be converted to SVG paths, but I haven't seen anything that does this. It seems that if SVG export is important, you need to stick to basic built-in font families to get results that look the same in the Browser and in the exported SVG.

All the best,
Curran

Jayson Harshbarger

unread,
Apr 28, 2016, 2:11:21 AM4/28/16
to d3-js
Hi Curran,

I had not even thought of externally loaded fonts.  Converting to SVG paths sounds way too complicated to be worth it.  As it is the generated SVG can be fairly large with all the inlined CSS styles.  SVGOMG (https://jakearchibald.github.io/svgomg/) helps with that.

Jayson
Reply all
Reply to author
Forward
0 new messages