Visual grouping
Open in a new window.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../build/ogma.min.js"></script>
<style>
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}
button {
position: absolute;
top: 10px;
left: 10px;
}
#custom-group-btn {
top: 40px;
}
</style>
</head>
<body>
<div id="graph-container"></div>
<button id="group-btn" onclick="toggleGroup()">Group by country</button>
<button id="custom-group-btn" onclick="toggleGroup2()">Group France & Brazil</button>
</body>
<script>
'use strict';
var FLAGS = {
'France': 'flags/fr.svg',
'Japan': 'flags/jp.svg',
'USA': 'flags/us.svg',
'Brazil': 'flags/br.svg'
};
var ogma = new Ogma({
container: 'graph-container'
});
ogma.styles.setHoveredNodeAttributes({ outline: null });
ogma.styles.setSelectedNodeAttributes({ outline: null });
ogma.parse.jsonFromUrl('files/countries.json')
.then(function (graph) { return ogma.addGraph(graph); })
.then(function () { return ogma.layouts.force({ locate: true }); });
ogma.styles.addNodeRule({
innerStroke: { color: '#555' },
image: {
url: function (node) { return FLAGS[node.getData('location')]; },
minVisibleSize: 0,
},
opacity: function (node) { return node.getData('open') ? 0.32 : undefined; },
badges: {
bottomRight: { stroke: { color: '#999' } }
}
});
var byCountry = null;
var customGroup = null;
// UI buttons
var buttonFranceBrazilOnly = document.getElementById('custom-group-btn');
var buttonGroupAll = document.getElementById('group-btn');
buttonFranceBrazilOnly.disabled = true;
function toggleGroup() {
// In case this is the first time, create the transformation, but do not trigger it yet
if (!byCountry) {
// 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.
byCountry = ogma.transformations.addNodeGrouping({
groupIdFunction: function (node) {
return node.getData('location');
},
nodeGenerator: function (nodes, country) {
var isVisible = country !== 'Japan';
return {
id: 'special group ' + country,
data: {
country: country,
open: isVisible
},
attributes: {
text: country,
// fixed radius for the nodes with hidden contents
radius: isVisible ? undefined : 20,
image: FLAGS[country]
}
};
},
showContents: function (node) {
return node.getData('open');
},
onCreated: function (metaNode, visible, subNodes, subEdges) {
if (visible) {
return ogma.layouts.force({ nodes: subNodes });
}
},
duration: 300,
enabled: false
});
}
// Toggle the grouping transformation now
byCountry.toggle().then(function () {
var buttonText = byCountry.isEnabled()
? "Ungroup by country"
: "Group by country";
buttonGroupAll.textContent = buttonText;
buttonFranceBrazilOnly.disabled = !byCountry.isEnabled();
return ogma.layouts.force();
});
}
function toggleGroup2() {
// In case this is the first time, create the transformation, but do not trigger it yet
if (!customGroup) {
customGroup = ogma.transformations.addNodeGrouping({
groupIdFunction: function (node) {
var id = node.getData('country');
if (id === 'France' || id === 'Brazil') return 'Level 2';
return undefined;
},
nodeGenerator: function (nodes, country) {
return {
id: 'special group ' + country,
data: {
country: country
},
attributes: {
text: country,
opacity: 0.32
}
};
},
// can be a function as well
showContents: true,
enabled: false,
onCreated: function (metaNode, visible, subNodes, subEdges) {
// do nothing here, in fact, this callback can be omitted then
}
});
}
// Toggle the grouping
customGroup.toggle().then(function () {
var buttonText = customGroup.isEnabled()
? "Ungroup France & Brazil"
: "Group France & Brazil";
buttonFranceBrazilOnly.textContent = buttonText;
return ogma.layouts.force();
});
}
ogma.events.onClick(function (evt) {
var target = evt.target;
if (target && target.isNode && target.isVirtual()) {
console.log('sub nodes', target.getSubNodes().getId());
}
});
ogma.events.onDoubleClick(function (evt) {
var target = evt.target;
if (target && target.isNode && target.isVirtual()) {
var country = target.getData('country');
target.setData('open', !target.getData('open'));
byCountry.refresh();
}
});
</script>
</html>