Matthew Milner: October 13, 2017 at 16:09
I opted to build a D3 visualization for family trees from scratch. It combines the layouts employed by existing D3 family tree visualizations with the data model used by D3's network graph visualizations (like that used in Webs). Like Webs, it takes its starting point from a series of 'core' nodes which act as the first generation of the tree, and then finds descendants using the particular verbs for the tree version you're interested in, down to the number of generations you've declared. Along the way, it checks to see if individuals in each generation have partners of some kind or another, documents their descendants as well, and if the partnership shares a descendant, combines the links like a normal family tree.
- Descent: fatherOf, motherOf, stepmotherOf, stepfatherOf, ward, adopted, fostered, godparentOf
- Union: husbandOf, wifeOf, married, civilpartnerOf, bedded
- Descent: masterOf, employed, apprenticed, master
- Union: partner, collaboratedWith, civilpartnerOf
- Descent: taught
- Union: [none]
- Descent: patronOf, brokerOf
- Union: [none]
Each "generation" isn't a biological generation per se, but a step away from the core nodes queried to create the tree. It is possible to show descent between generations as well, say in the case of a grandparent being the guardian of a grandchild. Importantly, the method of using initial or core starting points along with descent 'verbs' (edges for directed graphs) means that the visualization can't go 'up' the tree once it reaches the bottom - yet. Perhaps it should; that will cause some layout headaches however.
For each generation two separate queries are made - one for children, and the other for unions. Unions are inserted, alternating before and after, the initial individual. This allows for proper layout of the following generation, where children of the first individual appear first to the left, and then the next individual's children (and any they have in common with the individual to their left, to the left, and to the right, to the right etc.). Children are sorted according to the earliest dates available. If they're missing dates, they float to the left. If there are children who don't belong to a particular union, they float to the right, again sorted by date. Once unions are found, and individuals retrieved, the next generation is queried using all the individuals in that generation, following the same order layout of left to right. These Children are dumped into an array for later processing, and the cycle repeats.
The graph approach allows for linking of different types of relationships across and between generations. As each individual is added, their relationship is stored in a separate array with the following information: the verb or edge which defines it, whether it is legitimate or illegitimate, the kind of relationship denoted by the verb (in the case of family, whether the direct relationship is blood or by law, direct descent or inferred in some way), and whether it belongs to one or two individuals (parents etc.). Rather than using curved lines for the edges, I've opted for overlapping angular lines to give the appearance of traditional family tree branches.
Lastly, I wanted the trees to be interactive in some way, in order to allow for complex trees to showcase particular kinds of information. Clicking on an individual highlights them, and only shows their relationships - parents and children. In the tool box on the right, I've added buttons so users can pick which kinds of relationships they want to view in the tree.