Radial and Dendrogram Layouts
Alongside the four cartesian directions, ApexTree can place the root at the centre and lay each depth on its own ring. Combined with layoutType, this covers both the radial tree and the classic dendrogram.
Radial direction
Set direction: 'radial':
const tree = new ApexTree(document.getElementById('chart'), {
direction: 'radial',
nodeWidth: 90,
nodeHeight: 30,
})
const graph = tree.render(data)
The radial layout is a polar remap of the same Reingold-Tilford result the cartesian directions use, so parent-centring and contiguous per-subtree wedges carry over. The ring step grows automatically so crowded inner rings never collide.
Radial edges are cubic dendrogram links curved around the centre rather than straight spokes, which keeps sibling branches readable where they bunch up near the root.
Rank placement
layoutType decides where each rank sits along the growth axis:
| Value | Behavior |
|---|---|
'tree' (default) | Every node sits at a radius (or row) matching its own depth |
'cluster' | Every leaf is pinned to the deepest rank, so leaves line up on the outer ring |
'cluster' is what makes a true dendrogram. Internal nodes keep their natural depth either way:
const tree = new ApexTree(el, {
direction: 'radial',
layoutType: 'cluster',
})
layoutType applies to cartesian directions too, where 'cluster' pins leaves to the bottom row instead of the outer ring.
External labels
A dense radial tree usually reads better as small marker nodes with floating labels than as cards. Enable externalLabel and shrink the node box:
const tree = new ApexTree(el, {
direction: 'radial',
layoutType: 'cluster',
nodeWidth: 8,
nodeHeight: 8,
borderRadius: '50%',
externalLabel: {
enabled: true,
fontSize: '11px',
collisionStrategy: 'hide',
},
})
In a radial layout, labels fan out along their own spoke and flip 180 degrees on the left half of the dial so they stay readable rather than upside down.
Label collision
Inner rings have little arc length, so their labels collide long before the outer ones do. externalLabel.collisionStrategy thins them:
| Value | Behavior |
|---|---|
'none' (default) | Render every label, which may overlap when dense |
'hide' | Hide labels that lack tangential room on their ring, keeping a maximal, evenly spaced subset. Well-separated labels always survive |
'leaves' | Additionally drop every inner-node label, labelling only leaves, then still thin crowded leaves by arc length |
The spacing threshold is derived from the label fontSize, so a smaller font keeps more labels. This option only applies to direction: 'radial' and is ignored for cartesian layouts.
Expand and collapse buttons
Radial expand/collapse buttons are placed by ray-rectangle intersection along each node's growth direction, so a button sits on the outward edge of its node wherever it is on the dial.
What stays uniform
Two node features are cartesian-only and stay uniform in a radial layout:
autoNodeHeightmeasurement — every radial node keeps the globalnodeHeight- grouped leaf nodes (
groupLeafNodes)
Per-node nodeWidth / nodeHeight set through a node's own options still apply.
Switching at runtime
changeLayout() accepts 'radial' like any other direction, and the camera springs through the remap:
const graph = tree.render(data)
document.getElementById('btn-radial').onclick = () => graph.changeLayout('radial')
document.getElementById('btn-top').onclick = () => graph.changeLayout('top')
Complete example
const tree = new ApexTree(document.getElementById('chart'), {
direction: 'radial',
layoutType: 'cluster',
nodeWidth: 10,
nodeHeight: 10,
borderRadius: '50%',
siblingSpacing: 14,
childrenSpacing: 90,
edgeWidth: 1,
externalLabel: {
enabled: true,
fontSize: '10px',
collisionStrategy: 'leaves',
},
})
const graph = tree.render(flareHierarchy)
graph.fitScreen()