Appearance
Hierarchical sort siblings
This example shows how you can make the hierarchical layout sort the sibling nodes.
It can be usefull to quickly see which nodes are important in the hierarchy.
Just pass to the layout the path to a datafield in your nodes and Ogma will do the rest
Ordering of siblings is guaranteed, but the general ordering from left to right is not, because we prioritize decrossing over ordering.
ts
import Ogma from '@linkurious/ogma';
import './styles.css';
import chroma from 'chroma-js';
const ogma = new Ogma({
container: 'graph-container'
});
const colors = chroma.scale(['#FFD166', '#992535']).colors(10);
ogma.styles.addNodeRule({
color: n => (n.getData('sIndex') ? colors[+n.getData('pos')] : undefined),
text: {
content: n => `${n.getData('sIndex') || ''}`,
size: 18,
minVisibleSize: 0,
font: 'IBM Plex Sans'
}
});
ogma.styles.addEdgeRule({
width: 0.5
});
let shouldSort = true;
const input = document.querySelector('.switch')!;
input.addEventListener('click', evt => {
shouldSort = !shouldSort;
layout(shouldSort);
});
function layout(shouldSort: boolean) {
return ogma.layouts.hierarchical({
levelDistance: 50,
duration: 0,
siblingIndex: shouldSort ? 'sIndex' : undefined,
locate: true
});
}
const hasIndex = new Set([36, 8, 32, 35, 3, 2, 28, 27, 26, 1]);
const graph = await Ogma.parse.jsonFromUrl('files/dataflow-small.json');
let counter = 0;
graph.nodes.forEach((node, i) => {
if (!hasIndex.has(i)) return;
delete node.attributes;
node.data = { sIndex: i, pos: counter++ };
});
await ogma.setGraph(graph);
await layout(shouldSort);
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>
<div class="toolbar" id="ui">
<span for="sort">Sort siblings</span>
<span class="switch switch--horizontal">
<input type="radio" name="sort" value="sort" />
<input type="radio" name="sort" checked="checked" />
<span class="toggle-outside">
<span class="toggle-inside"></span>
</span>
</span>
</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);
}
body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
*,
*:before,
*:after {
box-sizing: border-box;
}
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}
.toolbar {
display: flex;
align-items: center;
gap: 5px;
position: absolute;
top: 20px;
right: 20px;
padding: 10px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
border-radius: 4px;
background: #ffffff;
color: #222222;
font-weight: 300;
}
/* -- CSS flip switch */
.switch {
width: 100%;
position: relative;
}
.switch input {
position: absolute;
top: 0;
z-index: 2;
opacity: 0;
cursor: pointer;
}
.switch input:checked {
z-index: 1;
}
.switch .toggle-outside {
height: 100%;
border-radius: 2rem;
padding: 0.25rem;
overflow: hidden;
transition: 0.25s ease all;
}
.switch .toggle-inside {
border-radius: 2.5rem;
background: #4a4a4a;
position: absolute;
transition: 0.25s ease all;
}
.switch--horizontal {
width: 5rem;
height: 2rem;
margin: 0 auto;
font-size: 0;
}
.switch--horizontal input {
height: 2rem;
width: 5rem;
margin: 0;
}
.switch--horizontal .toggle-outside {
background: #dddddd;
position: absolute;
width: 5rem;
}
.switch--horizontal .toggle-inside {
height: 1.5rem;
width: 1.5rem;
}
.switch--horizontal input:checked ~ .toggle-outside .toggle-inside {
left: 0.25rem;
}
.switch--horizontal input ~ input:checked ~ .toggle-outside .toggle-inside {
left: 3.25rem;
}
.switch--horizontal input:disabled ~ .toggle-outside .toggle-inside {
background: #9a9a9a;
}
.switch--horizontal input:disabled ~ label {
color: #9a9a9a;
}