Appearance
Group nodes
This example shows how to use the groupNodes transformation to group nodes depending on a criteria. In this case, we will group nodes by their location
data property.
js
import Ogma from '@linkurious/ogma';
const LOCATION = ['France', 'Russia', 'USA'];
const FLAGS = {
France: 'flags/fr.svg',
Russia: 'flags/ru.svg',
USA: 'flags/us.svg'
};
const duration = 300;
const randomGraph = (N, E) => {
const g = { nodes: [], edges: [] };
for (let i = 0; i < N; i++) {
const location = LOCATION[i % LOCATION.length];
g.nodes.push({
id: 'n' + i,
attributes: {
x: Math.random() * 100,
y: Math.random() * 100,
text: 'Node ' + i + ' - ' + location,
image: {
url: FLAGS[location]
}
},
data: {
location
}
});
}
for (let i = 0; i < E; i++) {
g.edges.push({
id: 'e' + i,
source: 'n' + ((Math.random() * N) | 0),
target: 'n' + ((Math.random() * N) | 0)
});
}
return g;
};
const g = randomGraph(10, 10);
const ogma = new Ogma({
graph: g,
container: 'graph-container'
});
ogma.styles.addNodeRule({
innerStroke: {
color: '#999'
},
badges: {
bottomRight: {
stroke: {
color: '#999'
}
}
}
});
let transformation = null;
document.getElementById('group-btn').addEventListener('click', () => {
if (!transformation) {
// Groups all active nodes that have the same `location` data property
// into a single node that will have the combined size of all nodes,
// and be at the center of the grouped nodes.
transformation = ogma.transformations.addNodeGrouping({
groupIdFunction: node => node.getData('location'),
nodeGenerator: (nodes, groupId) => {
return {
id: 'special group ' + groupId,
data: {
groupId: groupId,
subNodes: nodes
},
attributes: {
radius: nodes.reduce((acc, node) => {
return acc + node.getAttribute('radius');
}, 0),
text: groupId,
badges: {
bottomRight: {
text: nodes.size
}
},
image: FLAGS[groupId]
}
};
},
duration: duration
});
} else {
// Toggle the grouping
transformation.toggle(duration);
}
ogma.transformations.afterNextUpdate().then(() => {
ogma.layouts.force({ locate: true });
});
});
ogma.events.on('click', evt => {
if (evt.target && evt.target.isNode) {
const subNodes = evt.target.getData('subNodes');
console.log(subNodes && subNodes.getId());
}
});
// UI update
const onToggle = ({ target }) => {
const enabled = target.isEnabled();
const buttonText = enabled ? 'Ungroup nodes' : 'Group nodes';
document.getElementById('group-btn').textContent = buttonText;
};
ogma.events.on('transformationEnabled', onToggle);
ogma.events.on('transformationDisabled', onToggle);
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>
<button id="group-btn">Group nodes</button>
<script src="index.js"></script>
</body>
</html>
css
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}
button {
position: absolute;
top: 10px;
left: 10px;
}