wikitree / wikitree-dynamic-tree

Dynamically generated and browsed graphical family tree
MIT License
26 stars 20 forks source link

Allow a user to download an image of their Heritage Chart that they can share with others. #278

Open jmegenealogy opened 2 days ago

faceless2 commented 2 days ago

I know we've already spoken on this Jamie, but I'll add this comment for anyone else developing a WT tree app that generates an SVG, wants to make it downloadable and isn't quite sure where to start.

There is a method that does in this in SlippyTree which might be useful as something to base an implementation on. The process is fairly simple:

  1. Clone the SVG from the DOM to a new document
  2. Edit the cloned DOM as required - I'm adding metadata, adding the contents of the stylesheet inline in a <style> etc
  3. Serialize the XML to a String
  4. Turn the String into a Blob (https://developer.mozilla.org/en-US/docs/Web/API/Blob)
  5. Create a URL for the Blob (https://developer.mozilla.org/en-US/docs/Web/API/URL/createObjectURL_static)
  6. Create a new <a> element, add it to the document (hidden), set href and the download property to the filename.
  7. Simulate a click that begins the download, then - some time later - remove the link and deallocate the URL.

You can reference the stylesheet with <link> but adding it inline in a <style> makes the SVG standalone. Relative links to other resources (images, fonts, other stylesheets etc) make this more complicated.

Top tip number 1: add a stylesheet to your SVG which looks like this:

<style>
@page {
    size: 500px 300px; /* set to the size of your SVG */
    margin: 0
}
</style>

When opening the SVG in Firefox or Chrome and printing to PDF, this will set the size of the PDF page to the size of the SVG. As of today Firefox sometimes gets this wrong, but it will surely be fixed before long. Most specialised SVG-to-PDF converters will also support it, although Safari does not.

Top tip number 2: add metadata to describe your SVG - in particular, setting the date of the content makes a lot of sense, given how Wikitree data is always changing. I'm adding metadata that looks like this:

<title>WikiTree Slippy Tree for "Fryer-1646" as of Thu Oct 31 2024</title>
<metadata>
 <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <rdf:Description about="">
   <dc:title>WikiTree Slippy Tree for "Fryer-1646" as of Thu Oct 31 2024</dc:title>
   <dc:date>2024-10-31T10:23:21.511Z</dc:date>
   <dc:publisher>https://www.wikitree.com</dc:publisher>
   <dc:source>https://www.wikitree.com/apps/St.%20Claire-3#name=St.+Claire-3&amp;view=slippyTree&amp;slippyTreeState=AAH5HxgAJArkAAAkIxACAwMKAAGQo3UTAAHkVMQAAeR8sgAB-HVIAAH4iD4AAfkfGAAAAAAAABjedAAAGPGxAABOcZ8BAA</dc:source>
  </rdf:Description>
 </rdf:RDF>
</metadata>

RDF looks (and arguably is) horrendous but 95% is boilerplate, and it really only requires about three lines of code

When converting to PDF metadata is not currently very useful, as Chrome and Firefox respect the <title> but ignore the <metadata>. However this may change in the future, and other tools do make use of it.