Save and print a D3 generated SVG

11,844 views
Skip to first unread message

Gianluca Bisceglie

unread,
Jul 25, 2012, 12:04:17 AM7/25/12
to d3...@googlegroups.com
There appear to be various ways to accomplish a "save as" of SVG:


Would you recommend any library or well tested solution that works well with D3 generated SVG for both saving and printing?

Thanks,
Gian


Marc Fawzi

unread,
Jul 25, 2012, 12:06:00 AM7/25/12
to d3...@googlegroups.com
See FileSaver API discussion on this group 

Sent from my iPhone

Alex Reynolds

unread,
Jul 25, 2012, 12:20:43 AM7/25/12
to d3...@googlegroups.com
I ended up writing a small CGI script that takes SVG sent via Ajax, repackages it into a file and sends it back to the browser, which saves it wherever the user specifies. Clean and fast.

One disadvantage of the Flash-based option is that if you zoom in or out from the browser's default rendering level, the Flash widget does not change scale along with the rendered page. This is not a good design. I tried emailing the developer to get source code to try to fix this, but I did not get a response.

Another disadvantage is that Flash is quickly becoming obsolete technology, with one security hole after another. So people disable Flash (I do) or don't install it on newer computers. Having a Flash-free, HTML-only option allows supporting more users more easily and safely.

Finally, the CGI option is nice, because I can use whatever widget I like to trigger saving the SVG. I have full control over interface presentation and the mechanism of the save function.

-Alex

Gian

unread,
Jul 25, 2012, 1:37:32 AM7/25/12
to d3...@googlegroups.com, gianluca....@googlemail.com
Thanks for the links. The thread on this group is very informative. As anyone tried the following?

Phil Laliberte

unread,
Jul 25, 2012, 11:25:14 AM7/25/12
to d3...@googlegroups.com, gianluca....@googlemail.com
I've used canvg in one of my projects and I like it for the most part.  I ran into two problems with Canvg:

  1. Generating SVG from a d3 visualization that you have used transitions in will cause problems
    • canvg expects that transform statements are seperated by a space; such as 'translate(x,y) scale(1.5)'
    • D3 transitions create transitions without a space (which is generally fine); such as 'translate(x,y)scale(1.5)'
    • I've submitted a fix to the canvg author, but I don't think it has been included yet
  2. Text following a path will not work because this isn't currently supported by html5 canvas

Aaron

unread,
Jul 25, 2012, 11:47:34 AM7/25/12
to d3...@googlegroups.com, gianluca....@googlemail.com


On Wednesday, July 25, 2012 11:25:14 AM UTC-4, Phil Laliberte wrote:
I've used canvg in one of my projects and I like it for the most part.  
 
I am interested in doing this for performance issues (rendering thousands of SVG elements) could you provide some code or a small tutorial? did you do it server or client side?
Thanks a ton
a

Phil Laliberte

unread,
Jul 26, 2012, 11:00:20 AM7/26/12
to d3...@googlegroups.com, gianluca....@googlemail.com
I did it entirely on the client side.  Here is a small example in a jsFiddle.

I used this mainly to convert the result of my d3 work to PNG.

hugo

unread,
Jul 26, 2012, 11:43:09 AM7/26/12
to d3...@googlegroups.com, Phil Laliberte, gianluca....@googlemail.com
Might not matter to you, but I gave up on canvag because it doesn't work properly for SVGs that contain nested SVG tags.

Aaron

unread,
Jul 26, 2012, 2:34:23 PM7/26/12
to d3...@googlegroups.com, Phil Laliberte, gianluca....@googlemail.com


On Thursday, July 26, 2012 11:43:09 AM UTC-4, Hugo Shi wrote:
Might not matter to you, but I gave up on canvag because it doesn't work properly for SVGs that contain nested SVG tags.
Did you figure out an alterative? 

Ian Johnson

unread,
Jul 26, 2012, 5:47:52 PM7/26/12
to d3...@googlegroups.com, Phil Laliberte, gianluca....@googlemail.com
aaron, if you are looking for performance you might try phantomJS on the server side. I'm not sure if it will be the solution you are looking for, but allows you to rasterize svg in batches on as much hardware as you want.

if you have too many elements that you want to render real-time in the client i urge you to consider two things:
#1: do you need all those elements? can you more effectively communicate by taking a different view of the data
#2: render with canvas (not svg) you can still use some of d3's data manipulation functions and then draw to pixels with canvas
--
Ian Johnson

hugo

unread,
Jul 26, 2012, 5:53:49 PM7/26/12
to d3...@googlegroups.com, Aaron, Phil Laliberte, gianluca....@googlemail.com

On Thursday, July 26, 2012 11:43:09 AM UTC-4, Hugo Shi wrote:
Might not matter to you, but I gave up on canvag because it doesn't work properly for SVGs that contain nested SVG tags.
Did you figure out an alterative? 

well in our case we wanted png conversions in order to generate plot previews, in the short term, we're just using svg scale to render minimised versions as the preview, instead of generating pngs (i  guess the answer is no, I don't have an alternative for you =) )

we're actually mixing canvas in with our SVG now, and that makes it less likely that any png conversion tool would work for us.  Eventually I suspect we'll move entirely to canvas, it looks like KineticJS is giving us enough high level capabilities that we won't need d3.  we're mostly doing plotting, we're not really doing things with fancy transitions, so we're not using most of  d3s capabilities   Of course we've just started using kinetic, so, maybe we'll end up coming back =)

hugo

unread,
Jul 27, 2012, 3:32:48 PM7/27/12
to d3...@googlegroups.com, Aaron, Phil Laliberte, gianluca....@googlemail.com
for anyone who cares, our short investigation has indicated that kinetic js  is slower than SVG, so we're going to be looking at raw canvas.

arunkjn

unread,
Aug 3, 2012, 8:44:01 AM8/3/12
to d3...@googlegroups.com, gianluca....@googlemail.com
I am trying to use canvg to display a d3 visualization.
It is not displaying the linked css rules with the visuals, which is included as a file in html.
Can you share the fix with me?

richar...@gmail.com

unread,
May 13, 2013, 10:36:10 AM5/13/13
to d3...@googlegroups.com, gianluca....@googlemail.com

Just to dig up this old thread... maybe this is old news but I've just published a utility that lets you save SVG as a PNG without needing a server round-trip.

It goes via canvg to a PNG data-URL, then feature-sniffs the browser to try a couple of methods of saving the result. Still quite immature, but seems to work quite well for my use case. 

It suffers from the same limitations as canvg, the main one for me being the lack of support for CSS.

Anyway, it's here if you want to use it :

Scott Murray

unread,
May 13, 2013, 12:17:43 PM5/13/13
to d3...@googlegroups.com
Looks great! Nice to see an easy way to export to PNG (though the Mac’s built-in screen capture shortcuts do this, too, though less elegantly).

Re: SVG export, see SVG Crowbar: http://nytimes.github.io/svg-crowbar/

Scott

Chris Viau

unread,
May 13, 2013, 1:12:26 PM5/13/13
to d3...@googlegroups.com
Yeah! SVG Crowbar is inlining the styles!



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



John Delacour

unread,
May 13, 2013, 3:46:12 PM5/13/13
to d3...@googlegroups.com
On 13/5/13 at 17:17, s...@alignedleft.com (Scott Murray) wrote:

>...the Mac’s built-in screen capture shortcuts do this, too, though
>less elegantly).

The best way to do it on the Mac is to print to PDF (choose Save
as PDF... in the PDF pop up menu in the Print dialogue). That
way you will get a _vector_ pdf file and not a rasterized
version. This applies also to Firefox since at least a year
ago, and now, I see, even to Opera. The vector PDF can, of
course, be saved as a rasterized png, jpg etc. from Preview and
cropped or resized as required.

JD

Johnathan Mercer

unread,
May 22, 2013, 3:17:06 PM5/22/13
to d3...@googlegroups.com
Chris, thanks for the tip on SVG Crowbar!!

Chris Viau

unread,
May 22, 2013, 11:37:29 PM5/22/13
to d3...@googlegroups.com
I forward the thanks to Scott. I currently use https://github.com/Causata/svgenie, wrapping canvg and filesaver.js, and it's working pretty well. Without canvg, it's easy to convert from SVG to canvas and from canvas to png, but not SVG-canvas-png as there is a security feature preventing a tainted canvas to be converted. 

Artan Simeqi

unread,
Nov 23, 2013, 9:40:07 PM11/23/13
to d3...@googlegroups.com
I am using canvg with svgenie to save some svg images as png. I have had some succes with several simple cases but not with a graph drawn with d3 force layout. In the case of the graph only edges (lines) are exported to png. The nodes (circles) do not appear.

Has anyone been successful exporting a graph?

Phuoc Do

unread,
Dec 2, 2013, 1:34:26 PM12/2/13
to d3...@googlegroups.com
We setup an image generation service based on PhantomJS.


You can use Javascript to generate image and get base64 png json response. Feel free to send me an email if you have any problem.

Phuoc Do

Artan Simeqi

unread,
Dec 2, 2013, 6:42:35 PM12/2/13
to d3...@googlegroups.com
I have thought about the PhantomJS solution but is a bit tricky. The
graph is specific for a logged in user who sets the inputs for the
graph. So, I can't just pass a link to PhantomJS and have it rendered.
I would need to do some serious http gymnastics behind the scenes to
make this work.

Arun Jain

unread,
Dec 2, 2013, 10:54:30 PM12/2/13
to d3...@googlegroups.com

In that case you can extract the svg Dom as a string. Inject some global styles if necessary and send it to the server to rasterize as PNG.

You received this message because you are subscribed to a topic in the Google Groups "d3-js" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/d3-js/h3ELz1LdMLE/unsubscribe.
To unsubscribe from this group and all its topics, send an email to d3-js+un...@googlegroups.com.

Richard Klancer

unread,
Dec 3, 2013, 9:59:51 AM12/3/13
to d3...@googlegroups.com
Hi Artan,

A colleague of mine wrote an open-source Rack (i.e.,, Ruby server-side) app that uses the PhantomJS solution: https://github.com/concord-consortium/shutterbug

Take a look for example at http://lab.concord.org/interactives.html#interactives/sam/diffusion/4-2-semipermeable-two-barrier.json Expand the "SnapShots" section at the bottom of the page and click "snapshot interactive"

It supports HTML, SVG, and canvas elements (including WebGL canvases).

The client-side interface is pretty minimal:

var shutterbug = new Shutterbug('#sourceselector', '#outselector',optCallbackFn, optIdentifier);

$('#button').click(function() {
  shutterbug.getDomSnapshot();
});

This will replace the contents of $("#outselector") with an <img src="http://<yourhost:port>/gete_png/sha1hash> tag which will magically spring into existence.

As you can see, it does require jQuery.

Cheers, and HTH, 

--Richard Klancer

Artan Simeqi

unread,
Dec 3, 2013, 4:46:23 PM12/3/13
to d3...@googlegroups.com
Hi Richard,
I looked at the code and it looks very helpful. I think I will
translate the Ruby part to C# since my project uses MVC.Net

Thanks,
Artan
Reply all
Reply to author
Forward
0 new messages