In my last blog post, I walked through a network link chart example in sigma.js. In this post, I’ll do the same for a network link chart that is built using another popular data visualization library: d3.js. The syntax may be different, but the core concepts are the same. In my opinion, D3 is the better choice for building link charts with force directed layouts and node movement. However, Sigma was much easier to work with and probably has less of a learning curve for new developers. Due to its ease of use, I think Sigma has more customizable features and I have come to prefer it to D3’s link chart capabilities. Nevertheless, it is worth learning D3, so here is an example of a network link chart built using D3.
Now I will break it down piece by piece…
Unlike Sigma, there is only 1 required library to import:
The CSS is a lot heavier than Sigma though:
The visualization is again inserted into the div with id=network_graph. The code starts after the <script> tag. The first 3 segments are fairly straight forward. They set the height and width of the SVG element (the link chart is rendered as SVG instead of an image, so that it scales seamlessly), the color scale, and the start and end dates for the time slider. The time slider is an optional add-on, but I included it because it is useful for dynamic network analysis, or looking at changes in the links of a network over time.
The next 3 segments are also fairly easy to follow. The first sets up the force directed layout. Unlike Sigma’s force atlas algorithm, which converges on an optimized layout, the force layout in D3 continuously runs in the background, which means that every time a node is dragged, the force layout reestablishes a new position. The concept is similar to Sigma’s force atlas however: nodes are pushed the maximum distance apart while maintaining closeness in terms of connections. So nodes with many of the same connections appear closer together than nodes with very different connections. In the layout, charge is a variable that determines the spread of the nodes, much like a shot grouping pattern. Large negative numbers spread the nodes far apart. The section following the layout is standard D3 – it appends a SVG element to the network_graph div element. Right now the SVG is an “empty” object, but it will soon be bound to data. The last section below creates the tooltips that appear when a node is hovered over. Most of that code block is just the CSS for the tooltip, created as SVG object properties.
The section below sets a D3 time scale, and translates the boundaries of the scale to the start and end dates defined previously. The x-axis is then defined using the scale, a tick size, and padding between tick marks on the axis.
The next part of the code is a bit of a monster, but it handles the bulk of the creation of the network’s SVG elements. First the JSON data is read into D3 and stored as ‘netdata’. Then the date range for the dataset is discovered by parsing the data using the getDate() function. Note that d is used as the argument to the getDate function, and it will be used in other functions further down, because it is D3’s generic abbreviation for data. The code then loops through the links in the dataset and pulls the event_date (the date on which 2 nodes first connected) for each link. The min and the max become the range for the time slider later on. The force layout is then initiated, passing the nodes and links from netdata as the inputs. At this point, nothing has been created as an SVG. The next line starts the process by appending link SVG elements and binding the link data to them. The link thickness set as a function of the weight of a connection. Next, the nodes are created. The node color is set to the group or cluster, which in this case is the same for every node, but building the code this way allows for the possibility of coloring nodes by cluster. The mouse over methods are tied to the nodes so that the tooltips defined above appear on hover. There is also a method for double-clicking on a node, which focuses on that node and its connections. When the node is dragged, there is a call to the force layout, which re-optimizes the network’s layout after the node is dragged somewhere. The dragging ability is enabled by the SVG brush element, which is handily implemented by a D3 function. The next 2 blocks create the time slider along the x-axis, and the circles at each end of the slider. The properties appended to them are for style (translate moves the position of the slider to a certain location). The section after the slider creation calculates the screen coordinates for all of the nodes. The x, y coordinates and circle size are all calculated here. There are 2 sets of x, y coordinates because the coordinates are also used to determine the position of the links, and the start/end points for each link are the centers of the nodes. Lastly, there is a collide function that prevents nodes from overlapping.
The next function helps determine which nodes and links to remove (gray out) when the slider is moved. If the event_date of a link is greater than the slider value, then the opacity of the link and its associated nodes stays as it is, otherwise it is dropped to 0, which will make them all disappear.
The functions above are all that would be needed to build a basic network link chart with a time slider in D3. However, I added a few auxiliary functions for more finesse. The first separates the node circles with padding, to prevent any overlap. This function is called collide() and was called when the nodes were created above.
The next section enables the double-click action that was called when the nodes were created. A double-click focuses on one node and its network.
That’s all! It was a bit longer than the Sigma network, and a bit trickier to put together because of the way D3 creates SVG elements before there is any data bound to them, but it works just as well. As you saw, one advantage to D3 is that elements like sliders and other visualizations that use the data can be built in with little extra code. The same can be done for Sigma, but it requires custom JavaScript. In a future blog, I’ll show how an entire dashboard can be created with a Sigma network and other D3 visualizations bound to the same data. In this dashboard, interacting with the D3 visualizations will update the Sigma graph.