Sigma is a JavaScript library dedicated to graph drawing. It makes easy to publish networks on Web pages, and allows developers to integrate network exploration in rich Web applications.
The following example shows how simple it is to use sigma to display a JSON encoded graph file.
{
"nodes": [
{
"id": "n0",
"label": "A node",
"x": 0,
"y": 0,
"size": 3
},
{
"id": "n1",
"label": "Another node",
"x": 3,
"y": 1,
"size": 2
},
{
"id": "n2",
"label": "And a last one",
"x": 1,
"y": 3,
"size": 1
}
],
"edges": [
{
"id": "e0",
"source": "n0",
"target": "n1"
},
{
"id": "e1",
"source": "n1",
"target": "n2"
},
{
"id": "e2",
"source": "n2",
"target": "n0"
}
]
}
<html>
<head>
<style type="text/css">
#container {
max-width: 400px;
height: 400px;
margin: auto;
}
</style>
</head>
<body>
<div id="container"></div>
<script src="sigma.min.js"></script>
<script src="sigma.parsers.json.min.js"></script>
<script>
sigma.parsers.json('data.json', {
container: 'container',
settings: {
defaultNodeColor: '#ec5148'
}
});
</script>
</body>
</html>
Sigma provides a lot of built-in features, such as Canvas and WebGL renderers or mouse and touch support, to make networks manipulation on Web pages smooth and fast for the user.
The default configuration of sigma deals with mouse and touch support, refreshing and rescaling when the container's size changes, rendering on WebGL if the browser supports it and Canvas else, recentering the graph and adapting the nodes and edges sizes to the screen...
Sigma provides a lot of different settings to make it easy to customize how to draw and interact with networks. And you can also directly add your own functions to your scripts to render nodes and edges the exact way you want.
Sigma is a rendering engine, and it is up to you to add all the interactivity you want. The public API makes it possible to modify the data, move the camera, refresh the rendering, listen to events...
Sigma aims to help you display networks on the Web, from simple interactive publications of networks to rich Web applications featuring dynamic network exploration.
Update the data and refresh the drawing when you want. Bind custom functions to sigma's events to adapt the interactions to the needs of your application.
For more complex use cases, it is possible to develop and use plugins that add features to sigma. Some are already available on the repository, for animating the graph or apply a force-directed layout to your graph.
Let's assume we have a graph, exported in GEXF from Gephi, and we want to display it with sigma. In this tutorial, we will use the graph of character co-occurrences in Victor Hugo’s Les Misérables, available by default in Gephi.
But we also want highlight a node's neighborhood when it is clicked, by drawing every other nodes as grey.
Here, let's just assume that in our web page, we have an HTML element with the id sigma-container
to display our graph. This element's width and height can be whatever we want, and sigma will adapt the elements it adds into it by itself. Also, we must import sigma and add a script tag that will contain the JavaScript code.
Then, it's pretty easy: since sigma provides a plugin dedicated to load and parse GEXF graph files. So, all we have to do is to load the plugin and use it, as described in the plugin's documentation.
At this point, the graph should already be displayed, and manipulated with the mouse or touch:
<!-- [...] -->
<div id="sigma-container"></div>
<script src="path/to/sigma.js"></script>
<script src="path/to/sigma.parsers.gexf.min.js"></script>
<script>
sigma.parsers.gexf(
'path/to/les-miserables.gexf',
{ // Here is the ID of the DOM element that
// will contain the graph:
container: 'sigma-container'
},
function(s) {
// This function will be executed when the
// graph is displayed, with "s" the related
// sigma instance.
}
);
</script>
<!-- [...] -->
The first thing we need to do is to facilitate the way to retrieve the neighbors of a node. And the best way to do that is to add a method to the graph model.
Basically, the graph model provides a public access to the nodes and edges arrays, but it also maintains some more indexes accessible only from its methods, including the index of every neighbors for each node.
Then, we just need to bind functions to some events, that will first modify the colors of the nodes and edges, and then refresh the rendering.
And it's done!
<!-- [...] -->
<div id="sigma-container"></div>
<script src="path/to/sigma.js"></script>
<script src="path/to/sigma.parsers.min.gexf.js"></script>
<script>
// Add a method to the graph model that returns an
// object with every neighbors of a node inside:
sigma.classes.graph.addMethod('neighbors', function(nodeId) {
var k,
neighbors = {},
index = this.allNeighborsIndex[nodeId] || {};
for (k in index)
neighbors[k] = this.nodesIndex[k];
return neighbors;
});
sigma.parsers.gexf(
'path/to/les-miserables.gexf',
{
container: 'sigma-container'
},
function(s) {
// We first need to save the original colors of our
// nodes and edges, like this:
s.graph.nodes().forEach(function(n) {
n.originalColor = n.color;
});
s.graph.edges().forEach(function(e) {
e.originalColor = e.color;
});
// When a node is clicked, we check for each node
// if it is a neighbor of the clicked one. If not,
// we set its color as grey, and else, it takes its
// original color.
// We do the same for the edges, and we only keep
// edges that have both extremities colored.
s.bind('clickNode', function(e) {
var nodeId = e.data.node.id,
toKeep = s.graph.neighbors(nodeId);
toKeep[nodeId] = e.data.node;
s.graph.nodes().forEach(function(n) {
if (toKeep[n.id])
n.color = n.originalColor;
else
n.color = '#eee';
});
s.graph.edges().forEach(function(e) {
if (toKeep[e.source] && toKeep[e.target])
e.color = e.originalColor;
else
e.color = '#eee';
});
// Since the data has been modified, we need to
// call the refresh method to make the colors
// update effective.
s.refresh();
});
// When the stage is clicked, we just color each
// node and edge with its original color.
s.bind('clickStage', function(e) {
s.graph.nodes().forEach(function(n) {
n.color = n.originalColor;
});
s.graph.edges().forEach(function(e) {
e.color = e.originalColor;
});
// Same as in the previous event:
s.refresh();
});
}
);
</script>
<!-- [...] -->
Many different resources are available to help you, such as the Wiki, the examples and the plugins. And if your questions remain unsolved, you can post an issue on the Github repository.
The source code is tested, commented, and published on Github under the MIT License. And contributions are welcome! Please read the repository README.md file before sending pull requests.