Appearance
Hierarchical advanced
This example shows how to choose which node to place on top of the hierarchy. Click on a node to promote it at the top of the tree.
Click an edge to make its extremities the top of the layout.
ts
import Ogma, { HierarchicalLayoutOptions, Options } from '@linkurious/ogma';
import { GUI } from 'dat.gui';
import './styles.css';
const ogma = new Ogma({
container: 'graph-container',
renderer: 'canvas',
options: {
edgesRoutingStyle: 'vertical'
}
});
ogma.styles.addRule({
nodeAttributes: {
radius: 2,
color: '#0094ff'
},
edgeAttributes: {
shape: {
head: 'arrow'
}
}
});
const defaultLayoutOptions: HierarchicalLayoutOptions = {
direction: 'TB', // Direction of the layout. Can be TB, BT, LR, or RL,
// where T = top, B = bottom, L = left, and R = right.
duration: 300, // Duration of the animation
nodeDistance: 20, // Number of pixels that separate nodes horizontally in the layout.
levelDistance: 50, // Number of pixels between each layer in the layout.
componentDistance: 16, // Number of pixels between each component in the layout.
arrangeComponents: 'fit',
locate: {
easing: 'linear',
duration: 300
}
};
const ogmaOptions: Options = {
edgesRoutingStyle: 'vertical',
renderer: 'canvas'
};
const runLayout = (options: HierarchicalLayoutOptions) =>
ogma.layouts.hierarchical(options);
function runWithParameters() {
// create fresh new options
const newOptions: HierarchicalLayoutOptions = { ...defaultLayoutOptions };
console.log(defaultLayoutOptions);
// pass the roots to the layout
newOptions.roots = ogma.getSelectedNodes();
runLayout(newOptions);
}
const gui = new GUI({ name: 'Layout parameters', width: 330 });
// add general group
gui
.add(defaultLayoutOptions, 'levelDistance', 0, 100)
.name('Level distance')
.onChange(runWithParameters);
gui
.add(defaultLayoutOptions, 'nodeDistance', 0, 100)
.name('Node distance')
.onChange(runWithParameters);
gui
.add(defaultLayoutOptions, 'componentDistance', 0, 100)
.name('Component distance')
.onChange(runWithParameters);
gui
.add(defaultLayoutOptions, 'direction', {
'Top Down': 'TB',
'Bottom Up': 'BT',
'Left to Right': 'LR',
'Right to Left': 'RL'
})
.name('Direction')
.onChange(runWithParameters);
gui
.add(defaultLayoutOptions, 'arrangeComponents', {
Fit: 'fit',
Grid: 'grid',
Line: 'singleLine'
})
.name('Arrange components')
.onChange(runWithParameters);
gui
.add(ogmaOptions, 'edgesRoutingStyle', ['none', 'horizontal', 'vertical'])
.name('Edges routing')
.onChange(() => {
ogma.setOptions(ogmaOptions);
});
gui
.add(ogmaOptions, 'renderer', ['canvas', 'webgl', 'svg'])
.name('Renderer')
.onChange(() => {
ogma.setOptions(ogmaOptions);
});
const graph = await ogma.generate.balancedTree({
children: 2,
height: 5
});
// add some extra nodes to show multi-component packing
const extraNodes = Array.from({ length: 25 }).map((_, i) => {
return { id: 1000 + i };
});
graph.nodes = graph.nodes.concat(extraNodes);
await ogma.setGraph(graph);
ogma.getNode(0)!.setSelected(true);
runWithParameters();
ogma.events.on('click', evt => {
const target = evt.target;
// If the user clicked a node set it as root,
// otherwise pick the link ends and make them roots
if (target) {
if (target.isNode) {
target.setSelected(true);
} else {
target.getExtremities().setSelected(true);
}
}
runWithParameters();
});
html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<link
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;1,100;1,200;1,300;1,400;1,500;1,600;1,700&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="graph-container"></div>
<script type="module" src="index.ts"></script>
</body>
</html>
css
:root {
--base-font-family: 'IBM Plex Sans', Arial, Helvetica, sans-serif;
font-family: var(--base-font-family);
}
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}