So! You’ve created your super awesome SVG, and now you’d like to download that file. The good news is that this is pretty easy to do. Just a few lines attached to a click event.

Here’s the SVG details from the graphic shown above.

<svg id="canvas" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="600" height="400">
    <rect x="2" y="2" width="596" height="396" stroke="black" stroke-width="4" fill="none"></rect>
    <rect x="10" y="20" width="300" height="250" fill="darkred"></rect>
    <circle cx="350" cy="250" r="120" fill="darkblue"></circle>
    <text x="350" y="100" fill="green" font-size="24" font-family="'Lucida Sans Unicode', 'Lucida Grande', Helvetica, Arial, sans-serif" font-style="italic">Hello, World!</text>
</svg>

First, let’s make sure that we have fully defined our SVG by adding the appropriate namespace element. This isn’t something that I typically do all the time, but it is necessary for this to work correctly.

let svg = d3.select<SVGSVGElement, {}>("#canvas").attr("xmlns", "http://www.w3.org/2000/svg");

To force the download, we serialize the XML content, create a link, and click the link (from code). The code shown below is written in TypeScript. Figuring out the JavaScript should be trivial.

d3.select<HTMLButtonElement, {}>("#download").on("click", () => {
    let svg = d3.select<SVGSVGElement, {}>("svg").node() as SVGSVGElement;
    let serializer = new XMLSerializer();
    let source: string = '<?xml version="1.0"?>\n' + serializer.serializeToString(svg);
    let a = document.createElement("a") as HTMLAnchorElement;
    a.download = "image.svg";
    a.href = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source);
    a.click();
});

Once you have downloaded the file, you should be able to open the file in Inkscape, or any program that supports editing SVG files.

The complete script is available in Github.