d3export_demo
d3export_demo copied to clipboard
CSS Defined Styles are lost
One trouble with the XML serialization you are doing here is that CSS defined styles are lost. This is a problem I'm working on here: https://github.com/Hypercubed/svgsaver . If you include svgsaver in this project it might be as simple as replacing this line: https://github.com/agordon/d3export_demo/blob/master/index.html#L174 with svgsaver.getHTML(svg).
You might also eliminate the need for a server for downloading SVG and PNG (with some caveats)
Yeah that is a lot easier. Wish I had seen svgsaver before trying to mess around with CGI scripts.
For reference (as there aren't specific instructions here) I am making/testing visualisations in D3 and displaying them locally or on gist/ blocks. for the local work i was using the python SimpleHttpServer. for the download.pl script to work though you need to put download.pl in /cgi-bin in the root dir of your app, and then for installation of perl and the relevant cran modules. I had to install:
cpan
cpan[1]> install autodie
cpan[2]> install IPC::System::Simple
cpan[3]> install File::Slurp
I guess there is another way of installing these packages without using the cpan prompt, I have seen it and it looks messy, but tbh I don't really do perl. Anyway then you can do (for python 2.7, its different in python3):
python -m CGIHTTPServer
Then you can download your svg, but yeah as all you are doing is ripping out the svg and pinging it back as a file all the css is missing. I guess you could get the css too and concatenate that to the start of the svg_xml.
The svgsaver is much easier to deal with but will produce quite big svgs if you have a large number of elements as all the elements are individually styled, instead of copying the css across, which I think you can do for svgs. something like:
var svg = d3.select('svg').node();
var css = d3.select('style').node();
var svg_xml = (new XMLSerializer).serializeToString(svg.insertBefor(css,svg.firstChild));
Though this will actually modify the DOM which i guess is bad and also you wont get the correct css if you are using an @import or src or if the css is across multiple <style> tags. you could use
this to get the css:
var css = getElementChildrenAndStyles('svg')
Anyway it was all very interesting.
Are there plans to get SvgSaver onto a CDN?
Yes, right now svgsaver includes a lot of unnecessary style information in the SVG. This is something I am working on. For example we don't needed to keep redundant inherited styles. If you know beforehand you only rely on a subset of styles you can pass that set to the svgsaver constructor (https://github.com/Hypercubed/svgsaver/blob/master/src/svgsaver.js#L29). I need to document this.
I think one problem with copying the style element as you have shown is it will miss styles like this, since the container elements are not serialized.
#chart-div rect {
/* the styles */
}