I recently set out to learn how to draw family pedigrees with D3. Their website is full of examples including an actual pedigree chart. That example was much too simple for my requirements. I wanted it to be styled like most pedigrees in software with a box around the person. I also wanted it to expand, collapse, pan, and zoom. As I perused other D3 examples, I had difficulty mixing and matching techniques and separating the basics from the fancy stylistic additions. I decided to document and share what I learned in a incremental set of examples so that you wouldn’t have to become an expert in D3 just to draw a pedigree.
The D3 pedigree examples are hosted on GitHub. At the time of writing, they include 5 examples:
- Basic: A basic static pedigree.
- Expand and Collapse: Click on persons to expand and collapse the tree.
- Smooth Transitions: Changes are animated when the tree is expanded or collapsed.
- Ancestors and Descendants: Show both ancestors and descendants.
- Ancestors and Descendants - OOP: A more sane example of ancestors and descendants using classes.
Visit the repo to learn more about the implementation details. Here, I want to share my thoughts about whether D3 is a good tool for drawing pedigrees.
D3 has a built-in [tree layout]. It’s defaults need to be tweaked a little for rendering pedigrees, but it still works great.
Drawing the connecting lines is trivial in SVG.
Startup time for a basic pedigree is very small.
D3 is too powerful for most people to tame. Without being able to copy and paste from the enormous library of examples, most users would not be able to get anything done1. The moment you need to modify anything, you have to become an expert in both SVG and D3.
SVG is great for shapes with a little bit of text. But pedigrees are lots of text with a few shapes. SVG does not support text wrapping nor inline styles (the ability to style one word, character, or phrase different than the other text around it). You can mimic those feature by adding different text nodes and calculating their position, but it’s not ideal. Some browsers allow you to embed HTML in a
foreignObjectso that you can use HTML and CSS to style text, which has all the tools we need, but support is partial for those browsers that allow it while no version of IE supports it at all. That renders the
foreignObjectuseless for the majority of production projects.
The complexity increases by orders of magnitude if you want to make the pedigree dynamic and interactive (in our case to expand and collapse).
D3 does not lend itself well to an OOP approach. This is why the examples are generally one large wall of code.
If you just need a basic pedigree display than D3 is great. You’ll end up spending most of your time getting your data into the proper format than you will configuring the tree. However, if you need anything more advanced then I would recommend just using HTML. Ancestry, FamilySearch, and findmypast all use HTML for their pedigrees. MyHeritage is the only large tree website I know of that uses SVG and they didn’t use D3 to do it.
I don’t think I could’ve done anything either without those examples. ↩