Reinventing the wheel to draw wide tree hierarchies
Reinventing the wheel to draw wide tree hierarchies. Recently, the author spent a week trying to figure out how to display a very large inheritance tree on a limited amount of screen space. Libraries like D3 excel at creating hierarchies, but they tend to group nodes of a certain depth or all leaf nodes together, leading to wide diagrams with many siblings.
To address this issue, the author decided to generate words instead of rendering the inheritance tree top-to-bottom. This approach ensures words are easier to read while maintaining the tree structure.
To create the words, the author used English language letter frequencies, accumulating and normalizing them to 1. By separating vowels and consonants, the author ensured alternating sounds to avoid unpronounceable pairs. The resulting words resemble a single trunk with branches, similar to a wooden tree. The author defined a simple text format for displaying parent nodes and their children, separated by hyphens.
The visualization initially displayed only a placeholder text, but the author emphasized the importance of correctly positioning nodes. Each node was represented as a rectangular box with centered text. The renderNode function returned a single g element for easy transformation and positioning. The measureBbox helper function calculated the bounding box of the rendered text, which aided in creating an appropriately-sized rectangle around it.
To connect nodes, the author used a step connection style with four points, starting from the bottom edge of the parent at its center, moving downwards, then horizontally to the child's center, and finally downwards again. The line's position was determined using move and vertical/horizontal commands. The bounding box of each node was cached to avoid recomputation.
The layout algorithm arranged nodes into columns and rows. Leaf nodes had a size of 1x1, while columns were as wide as the widest child, and rows were as tall as the tallest child. Columns' height was the sum of all their children's heights, and rows' width was the sum of all their children's widths. The link between parent and children nodes was persisted in the leaf nodes, allowing easy reference after creation.
To improve layout, the author introduced staggered rows for non-leaf nodes, reducing crossing lines. However, some links were jagged due to bounding boxes overlapping the parent's center. To address this, the author connected straight lines when the children's bounding boxes were within the parent's center, improving the visual appearance of the tree.
Written by urgent.news from Lobsters's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.