<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="../build/ogma.min.js"></script>
<style>
body,
html {
font-family: Helvetica, Arial, sans-serif;
}
#graph-container {
top: 0;
bottom: 0;
left: 0;
right: 0;
position: absolute;
margin: 0;
overflow: hidden;
}
button {
position: absolute;
top: 10px;
left: 10px;
}
#group-layout-btn {
position: absolute;
top: 40px;
}
#layout-btn {
top: 70px;
}
#legend {
display: block;
position: absolute;
bottom: 20px;
left: 20px;
}
#legend ul {
list-style: none;
}
#legend ul li .color {
display: inline-block;
width: 1em;
height: 1em;
margin-right: 5px;
}
</style>
</head>
<body>
<div id="graph-container"></div>
<button id="group-btn" onclick="toggleGroup()">Group articles by field</button>
<button id="group-layout-btn" onclick="layoutGroup()" disabled>Layout selected group</button>
<button id="layout-btn" onclick="layoutGraph()">Layout graph</button>
</body>
<script>
var ogma = new Ogma({
container: 'graph-container'
});
var names = {
'rgba(51, 153, 255, 1)': 'Arctic, communities',
'rgba(0, 204, 204, 1)': 'Research',
'rgba(153, 255, 255, 1)': 'Population',
'rgba(255, 204, 51, 1)': 'Aerospace',
'rgba(255, 204, 102, 1)': 'Geosciences',
'rgba(255, 255, 51, 1)': 'Physics',
'rgba(102, 0, 102, 1)': 'Petrol',
'rgba(153, 0, 0, 1)': 'Political Studies',
'rgba(102, 102, 0, 1)': 'Pollution',
'rgba(0, 153, 0, 1)': 'Energy resources',
'rgba(153, 255, 0, 1)': 'Biodiversity',
'rgba(0, 204, 51, 1)': 'Global warming',
};
function toggleButton(on) {
var button = document.getElementById('group-btn');
button.innerHTML = on ? 'Ungroup' : 'Group articles by field';
}
// toggle group layout button based on whether there are selected groups
function onSelectionChange(evt) {
var nodes = evt.nodes;
var metaNodes = nodes.filter(function (node) {
return node.getSubNodes() !== null;
});
var button = document.getElementById('group-layout-btn');
if (metaNodes.isSelected().some(function (selected) { return selected })) {
button.removeAttribute('disabled');
} else {
button.setAttribute('disabled', 'disabled');
}
}
ogma.events.onNodesUnselected(onSelectionChange);
ogma.events.onNodesSelected(onSelectionChange);
ogma.styles.addNodeRule({
innerStroke: { width: 0.1, scalingMethod: 'scaled' }
});
ogma.parse.gexfFromUrl('files/arctic.gexf')
.then(function (graph) {
return ogma.setGraph(graph);
})
.then(ogma.view.locateGraph)
.then(function () {
var colors = ogma.getNodes().getAttribute('color').reduce(function (acc, c) {
if (c !== undefined) acc[c] = c;
return acc;
}, {});
var legend = document.createElement('div');
legend.setAttribute('id', 'legend');
var legendHtml = ['<ul>',
Object.keys(names).map(function (color) {
var name = names[color];
return '<li><div class="color" style="background-color: ' + color + '"></div>' + name + '</li>';
}).join('\n'),
'</ul>'].join('\n');
legend.innerHTML = legendHtml;
document.body.appendChild(legend);
var byColor = ogma.getNodes().getAttribute('color')
.reduce(function (acc, color) {
acc[color] = [];
return acc;
}, {});
ogma.getNodes().forEach(function (n) {
byColor[n.getAttribute('color')].push(n.getId());
});
Object.keys(byColor).forEach(function (color) {
ogma.getNodes(byColor[color]).fillData('groupId', color);
});
});
var transformation = null;
function toggleGroup() {
if (transformation === null) {
transformation = ogma.transformations.addNodeGrouping({
groupIdFunction: function (node) {
return node.getData('groupId');
},
nodeGenerator: function (nodes, groupId) {
return {
id: 'special group ' + groupId,
data: {
groupId: groupId,
},
attributes: {
text: names[groupId] || 'Other',
color: groupId,
opacity: 0.32
}
};
},
edgeGenerator: function (edges, id) {
return {
id: id,
attributes: {
// logarithmic scale for the grouped edges width
width: 1 + Math.log(edges.size),
opacity: 0.5
}
};
},
showContents: function (metaNode) {
return true;
},
onCreated: function (metaNode, visible, subNodes, subEdges) {
if (visible) {
subNodes.setAttributes(
Ogma.geometry.computeCentroid(subNodes.getAttributes(['x', 'y']))
);
return ogma.layouts.force({
nodes: subNodes,
duration: 0,
useWebWorkers: false
})
}
}
});
transformation.whenApplied().then(function () {
toggleButton(true);
return layoutGraph();
});
} else {
transformation.toggle().then(function () {
if (transformation.isEnabled()) {
toggleButton(true);
return layoutGraph();
} else {
toggleButton(false);
}
});
}
}
function layoutGroup() {
ogma.layouts.force({ nodes: ogma.getSelectedNodes().getSubNodes()[0] });
}
function layoutGraph() {
return ogma.layouts.force({
// parameters selected for speed and similarity
// to the initial layout
steps: 150,
charge: 0.125,
gravity: 0.01,
edgeStrength: 1,
theta: 0.9,
locate: true
});
}
</script>
</html>