chiasm-project / chiasm

A browser based environment for interactive data visualizations.
MIT License
184 stars 27 forks source link

SVG Download Button #48

Open curran opened 8 years ago

curran commented 8 years ago

Create an example that has a "download SVG" button. When clicked, the SVG document you are seeing within the current instance of chiasm-layout should be downloaded into a .svg file. The file should contain the SVG trees from multiple components (e.g. a line chart and bar chart together). The download button should be implemented as a Chiasm component and included on the page via chiasm-layout.

Start from these examples:

After this is done, new issues should be created for creating similar buttons "Download as PNG" and "Download as CSV".

Hypercubed commented 8 years ago

I have an angular plugin that does just that: https://github.com/Hypercubed/angular-downloadsvg-directive . Downloading the SVG is easy enough but ensuring that all appropriate styles are copied from stylesheets to the elements is difficult. My approach is a whitelist of SVG appropriate styles. Right now this module is dependant on angular and jQuery. I'm interested in making a stand alone version (dependent only on FileSaver).

Here it is working with chiasm: http://hypercubed.github.io/Project-Chi/#/examples/chiasm

Hypercubed commented 8 years ago

Hello @curran, I'm working on a module that will download cleaned SVGs along with computed CSS styles here. Your​ input would be appreciated.

curran commented 8 years ago

Hello @Hypercubed , this is really cool! I finally got a chance to look at the demo link you sent, it looks amazing and the SVG download works like a charm. I'd like to try spending more time with your code, the system looks really nice. It's interesting to see the functionality split across views, with the Chiasm runtime in its own box, and the input files (config and data) in a separately managed box with tabs where the changes propagate through. Very nice.

I cloned your svgsaver repo and got the tests to run on my machine. I will explore the code more. I can see this library as potentially being wrapped as a Chiasm plugin that displays the download button and reaches into the layout plugin to get the SVG out.

Ideally the button could appear in the corner of a visualization. This is related to the goal of having the layout plugin support a "z" orientation where components are layered on top of one another.

I'm excited to see you have this working. Very nice progress!

curran commented 8 years ago

I created a repository chiasm-svgsaver for a Chiasm component that wraps around svgsaver. The first thing I encountered is that svgsaver is not published to NPM, so I cannot add it as a dependency. Could you please publish it to NPM? Thanks!

Hypercubed commented 8 years ago

I haven't published it on npm yet because I not happy with the API yet. Also, not very satisfied with the name.

You should be able to do npm install Hypercubed/svgsaver to install directly from github.

Hypercubed commented 8 years ago

I'm also looking at saveSvgAsPng. It takes a different approach to downloading not requiring FileSaver.

Hypercubed commented 8 years ago

svgsaver is now on npm. However, it requires https://github.com/eligrey/FileSaver.js/ which is not published to npm. I may need to use an alternative version or bundle FileSaver.js.

Hypercubed commented 8 years ago

I'm trying https://github.com/carlos-algms/FileSaver.js in svgsaver, so the dep issue should be fixed. Not sure how to wrap this into a chiasm plugin.

curran commented 8 years ago

Not sure if you've seen it but also check out this example Download SVG from Data URL. This downloads a file from the browser, and the code is very small.

Hypercubed commented 8 years ago

Yes, but it's not cross browser compatible. I don't have the details now but FileSaver does the same thing when the browser is compatible and has fallbacks when not. I might include a small saveAs shim in svgsaver then provide instructions for loading FileSaver when broader browser support is needed.

Hypercubed commented 8 years ago

I've added a tiny shim that allows downloads in Chrome. For downloading in other browsers and for PNG download (recently added) you need to install eligrey/FileSaver.js/ and eligrey/canvas-toBlob.js. I'd like to get this working in a chiasm plugin but where do I start. Should it add a floating button outside the layout? Do you have an example of this?

curran commented 8 years ago

Ah yes, I see what you mean.

In terms of a place to start, I think this Chiasm Boilerplate would be good. Maybe as a first step you could copy and modify the ColoredRectangle plugin to download the SVG extracted from chiasm-layout when you click on the square. Next it could be changed to display a download icon. This would be a great step forward, but the button would be occupying a box within the nested box screen real estate of the layout.

For adding it as a floating button, I was thinking to add a "z" orientation option in chiasm-layout for having things layered on top of each other rather than in adjacent boxes. This could be used to float the button above visualizations in the layout and perhaps specify its size. I'm not sure how exactly this would look though - maybe the layout could somehow specify that it should show up in a certain corner, and have a fixed width and height in pixels.

The closest thing I have so far is the gear in the corner of this example Live Temperature by City, which is created by custom code outside of the Chiasm layout. This is another use case for floating button support in chiasm-layout - then the gear could become its own component.

Hypercubed commented 8 years ago

I did the first part, forked the biolerplate and added a downloadButton plugin. I used ownerSVGElement to get the parent SVG. http://bl.ocks.org/Hypercubed/b01a767b41b0e679aade

Hypercubed commented 8 years ago

I made a first cut at chiasm-svgsaver at Hypercubed/chiasm-svgsaver.

curran commented 8 years ago

Wow, this is amazing! This is exactly perfect as a first pass. Thank you for taking the time to do this work, I really appreciate it. It's really nice how you managed to get it to load svgsaver using the script tag globals pattern as well as via Node.js dependencies. I think I'll go ahead and merge your fork.

Hypercubed commented 8 years ago

I struggled with the loading. I'm writing this as an ES6 module converting to CJS and UMD. The browser can use UMD directly. I would like JSPM to use ES6 but that introduces a problem (see here https://groups.google.com/forum/#!topic/systemjs/FH1reibV924). So, for now, JSPM uses the CJS version. And while svgsaver can be used as a node dependency (as I did in the mocha test) it really has no function, both the copying the CSS styles and downloading of the SVG requires the DOM. I had to make FileSaver.js optional in order for it to load in node at all (FileSaver is not node safe).

Be sure to look here at my browser compatability notes: https://github.com/Hypercubed/svgsaver/wiki/Compatibility-Chart . Something about this should be added to chiasm-svgsaver's readme.

curran commented 8 years ago

I just came across svg-crowbar, which is amazing.

Hypercubed commented 8 years ago

Yes.... my version using svgsaver: http://hypercubed.github.io/svgsaver-crowbar/

curran commented 8 years ago

Wow, that's amazing! Great work.

I tried exporting all of my bl.ocks as SVG and the result was interesting. Some of them failed completely due to, for example, a black background being encoded outside of the SVG. It also made me realize that I had been relying heavily on the bl.ocks titles for context, and that for printing/exporting, the title and perhaps some descriptive text would be useful.

Do you do a lot of work that requires exporting images? For publications maybe?

Looking forward to iterating more on chiasm-svgsaver, thanks again for putting that together. I think I'd like to make it appear as a download icon, then it can be used with other small components to build a toolbar-like interface in a narrow strip at the top of a Chiasm visualization.

Hypercubed commented 8 years ago

The advantage of svgsvaer (over svg-crowbar and others) is the inlining of CSS styles (also PNG download). However, this will fail in some cases because of iframes (svg-crowbar doesn't have this issue). There might be a work around but I haven't looked at it closely.

Yes, typically a researcher will include screenshots in publication submissions then, when the paper is accepted, they suddenly need high quality PDFs with vector images. That is the reason I spend a lot of time on svgsaver.

You might also look at plotly.js. They have a nice toolbar that includes a download button. However svgsaver wont work in their system because they create their visualizations by layering multiple SVGs.