4 ms·
Not sure if it fits your use case, but; for one project I needed to have charts that the user could modify in their browser, and once they were happy they could
by m0j0l 10y ago
Not sure if it fits your use case, but; for one project I needed to have charts that the user could modify in their browser, and once they were happy they could hit 'download PDF' to get a PDF version.
Achieved this by (admittedly slightly clunky way) of sucking the SVG out of the chart and sending it to the server via ajax. Server intercepts SVG and passes it to inkscape which does pretty good command line svg -> pdf... then, sends back completed PDF.
One gotcha is that you won't get any CSS this way, so all styling has to be done via SVG props.
- e1g 10y agoThat's exactly what we are doing but running the SVG code through Apache Batik Rasterizer to turn it into png. I like this approach because the user can customise the chart in the front end and then the same resulting svg code is rendered by the backend. The only issue is styling as you mentioned.
- Frencil 10y ago> One gotcha is that you won't get any CSS this way, so all styling has to be done via SVG props. There actually is a way to bake stylesheets directly into the SVG in a way that at least Inkscape can read, but it's tricky. We're successfully doing this in a graphing library tuned for genetic data that's built on top of d3 called LocusZoom. The first step is to get the content of the stylesheet into a string. We do that here with a CORS request in case the stylesheet is being loaded over a CDN, as javascript won't be able to access the content of CDN-loaded stylesheets from document.styleSheets: https://github.com/statgen/locuszoom/blob/v0.4.0/assets/js/app/Instance.js#L808 https://github.com/statgen/locuszoom/blob/v0.4.0/assets/js/a... Since the stylesheet doesn't change once the page is loaded this only needs to happen once. From there, in our case, we have a dynamic/interactive SVG plot so the download needs to bundle up the current state of the SVG on request. Here's the method that does that: https://github.com/statgen/locuszoom/blob/v0.4.0/assets/js/app/Instance.js#L783 https://github.com/statgen/locuszoom/blob/v0.4.0/assets/js/a... Other than what no doubt looks familiar for pulling the raw SVG markup into a string we also insert a tag right after the opening <svg> tag that looks like this: "<style type=\"text/css\"><![CDATA[ " + this.css_string + " ]]></style>" Where this.css_string is our stylesheet content. We then base64 encode the string and stick in the href of an <a> tag styled to look like a download button as seen here: https://github.com/statgen/locuszoom/blob/v0.4.0/assets/js/app/Instance.js#L748 https://github.com/statgen/locuszoom/blob/v0.4.0/assets/js/a... The end result is a download SVG link/button that is 100% client-side with our chosen stylesheet embedded. Now, I have noticed that some styles defined in the stylesheet are valid in the browser but fail in InkScape and other SVG viewers. A prime example would be setting a stroke or fill to "transparent". InkScape doesn't interpret this properly and you can end up with solid black, just about the exact opposite of transparent. Keeping this in mind I stick to defining explicit "fill-opacity" and "stroke-opacity" values in the stylesheet for SVG elements and everything plays nice. A working demo of this can be seen here: http://statgen.github.io/locuszoom/plot_builder.html http://statgen.github.io/locuszoom/plot_builder.html