Hacker News new | ask | show | jobs
by Someone1234 3932 days ago
You could use this to convert from SVG to a Canvas element and then from Canvas to an image (via canvas.toDataURL("image/png")):

https://github.com/gabelerner/canvg

Still needs a very newish browser however. No IE 6-8 (& 9?) support.

2 comments

Yeah, it's a pickle. Raphael supports limited subset of SVG with VML failover compatibility, but export is limited because you have to support two technologies.

Then it gets weirder because RaphaelJS isn't exactly responsive-ready. Takes some work to make graphics just resizable (you can scale with the viewbox, but that's about it.) Recently, I switched to pure SVG (even when programmatically generated) because nested SVG elements provide basically a mechanism for relative/responsive scaling, positioning and such.

The guy who came up with RaphaelJS was ahead of his time, and I believe he got hired by Adobe in part thanks to the project's exposure. The development stopped awhile back, and it shows, which is really sad because I liked how the programming style for Raphael is done.

I would prefer the SVG itself but this is an ideal short term solution. Thank you very much!
I have written two ways of exporting SVG that you can inspect here: http://staticresource.com/sketch.html

One takes the SVG from the browser, encodes it and sends the <svg> as the body of an email (inlined, not as an attachment). Here's the relevant part:

    function render() {
      var link = document.createElement('a'),
          time = Date.now();
      link.href = 'mailto:?  subject=exported%20sketch&body=%3C%3Fxml%20version%3D%221.0%22%20standalone%3D%22no%22%3F%3E%3C!DOCTYPE%20svg%20PUBLIC%20%22-%2F%2FW3C%2F%2FDTD%20SVG%201.1%2F%2FEN%22%20%22http%3A%2F%2Fwww.w3.org%2FGraphics%2FSVG%2F1.1%2FDTD%2Fsvg11.dtd%22%3E'+encodeURIComponent(new XMLSerializer().serializeToString(board));
      link.id = time;
      document.body.appendChild(link);
      document.getElementById(time).dispatchEvent(new MouseEvent('click'));
      document.getElementById(time).parentNode.removeChild(document.getElementById(time));
    }
The other prepares it as a file and creates a download link (not seen on screen) and programmatically clicks that link to download it:

    function download() {
      var link = document.createElement('a'),
          time = Date.now(),
          svg = '<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">'+new XMLSerializer().serializeToString(board);
      link.id = time;
      link.setAttribute('download','sketch.svg');
      link.href = 'data:text/html;charset=utf-8,' + encodeURIComponent(svg);
      document.body.appendChild(link);
      document.getElementById(time).dispatchEvent(new MouseEvent('click'));
      document.getElementById(time).parentNode.removeChild(document.getElementById(time));
    }
But be forewarned, since SVG uses XML namespaces instead of HTML, using things like '.innerHTML' won't work in certain browsers (iOS Mobile Safari for example) while innerHTML does tend to work as you would expect on most desktop browsers!

Canvas would work for exporting a bitmapped snapshot of the vector, but lacks the following:

- filesize: SVG is vector, but Canvas renders a bitmap

- non-destructive: SVG is human-editable after the fact, bitmaps only 'remember' the value of the top-most pixel and 'forgets' everything that has overlapped

- human-editable: Though not pretty, SVG's can be read and edited by hand, bitmaps require a graphics tool to edit easily