Appearance
Group edges
This example shows how to group parrallel edges by using the edgeGrouping transformation.
ts
import Ogma, { Color, EdgeGrouping } from '@linkurious/ogma';
const NB_EDGES = 10;
const COUNTRY = ['France', 'Russia'] as const;
type Country = (typeof COUNTRY)[number];
type NodeData = {};
type EdgeData = { country: Country };
const ogma = new Ogma<NodeData, EdgeData>({
container: 'graph-container'
});
const COLORS: Record<Country, Color> = {
France: '#de1d4d',
Russia: '#1d60de'
};
ogma.addNodes([
{ id: 'n0', attributes: { x: -50, y: -50 } },
{ id: 'n1', attributes: { x: 50, y: 50 } }
]);
ogma.styles.addEdgeRule({
color: edge => COLORS[edge.getData('country')] || 'grey'
});
ogma.view.locateGraph();
for (let i = 0; i < NB_EDGES; i++) {
const country = COUNTRY[(Math.random() * COUNTRY.length) | 0];
ogma.addEdge({
id: 'e' + i,
source: 'n0',
target: 'n1',
attributes: {
text: country,
width: 2
},
data: { country }
});
}
let transformation: EdgeGrouping<EdgeData, NodeData> | null = null;
document.getElementById('group-btn')!.addEventListener('click', () => {
const duration = (document.getElementById('animation') as HTMLInputElement)
.checked
? 500
: 0;
if (!transformation) {
// Groups all parallel edges that have the same data.country property
// into meta-edges which the size is the sum of every edge and
// the text is the content of data.country:
transformation = ogma.transformations.addEdgeGrouping({
groupIdFunction: edge => edge.getData('country'),
generator: (edges, groupId) => ({
data: {
subEdges: edges.getId(),
country: edges.getData('country')[0]
},
attributes: {
width: edges.reduce((width, edge) => {
return Number(edge.getAttribute('width')) + width;
}, 0),
text: groupId
}
}),
duration
});
} else {
transformation.toggle(duration);
}
// After the next transformation update takes place, update the button content
ogma.transformations.afterNextUpdate().then(() => {
const buttonText = transformation?.isEnabled()
? 'Ungroup edges'
: 'Group edges';
document.getElementById('group-btn')!.textContent = buttonText;
});
});
ogma.events.on('click', evt => {
if (evt.target && !evt.target.isNode) {
const subEdges = evt.target.getData('subEdges');
if (subEdges) console.log('sub edges:', subEdges);
}
});
html
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<link type="text/css" rel="stylesheet" href="styles.css" />
</head>
<body>
<div id="graph-container"></div>
<div class="controls">
<button id="group-btn">Group edges</button>
<label for="animation"
>Animated: <input id="animation" type="checkbox" checked
/></label>
</div>
<script src="./index.ts"></script>
</body>
</html>
css
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}
.controls {
position: absolute;
top: 10px;
left: 10px;
background: #fff;
padding: 10px;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
border-radius: 5px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
.controls label {
display: block;
margin-top: 10px;
}