D3 Network Chart (early development)

The Challenge

Most company’s have work flow processes where a piece of work is passed from department to department step by step until its marked as completed. Some processes are well defined, ridged and are simple to map out and others take on a more random path depending on their unique requirements, sometimes looping around the same department several times before it can be marked complete. Ideally I would have loved to work with a defined process where I could map data onto clear info-graphs (see below), perhaps the project will lead there, but for now I’m working with dynamic data.

Contenders:

  1. Network
  2. Sankey
  3. Chord

Each chart was visualized with example data to quickly see how they performed.

Sankey was eliminated as the process wasn’t fixed and there could be random loops…

Chord diagram was difficult to analysis so the decision was made to use the Network Chart as the starting point although I needed to do more with it, I wanted the process to flow left to right from the open to closed action with all the work nodes in the middle. Off the shelf network charts used force to determine where a node would be positioned, this would be random and as such you couldn’t see the left to right flow as you were always looking for those start end end point. For this to work I decided to create a bespoke extension using D3.

Initial set of requirements

  • Determine the position of the nodes and lock them in place
  • Allow the user to move a node if required
  • Draw paths from each node
  • Path thickness to indicate volume
  • Arrow on path to indicate direction of travel
  • RAG status of the directional arrows
  • Fit the node name into the circle by wrapping the label
  • Colour code the nodes by dimension
  • Add PopUps for the nodes and RAG arrows

 

Development

First I used a basic Network Chart from Holtz Yan (https://www.d3-graph-gallery.com/graph/network_basic.html) to give me the basic building blocks. One issue which I didn’t notice was it used version 3 D3, the Network commands for V5 are different although as I was too far into the project before I realized I continued with version 3… This of course may cause a problem in the future if more requirements are added but for now its fine.

Next I started working through my requirements… I created a JSON file which held x and y coordinates of all the nodes (plus additional data), turned off the network force settings to lock them in place.

Network V1

 

I changed the paths so they linked between the nodes and updated the code to allow the nodes to be moved by the user but still remain in their new position. For this turned back on the tick. removed the force and added this code to lock the position of the node.

(when appending the nodes)
.classed("fixed", function (d,i){d.fixed = true})
.call(drag)
function dragstart(d) {
  d3.select(this).classed("fixed", d.fixed = true);
}
Paths were a challenge as you can see below. I didn’t want them to go over the node but I needed to see the arrow head, sending them to the back (rendering them first) would solve the first problem but would then hide the arrow head…

Network V2

I resolved issue with two paths. The first goes from the center of the source to target node, rendered first so its layered behind the node. The second path is invisible and only goes half the distance, the arrow is placed at the end of that path so appears to be in the middle of the first….

Network V3

Up until now the node name was just giving me back x and y data so I could see them updating. Changing the label to the node name became as big issue to resolve because of text wrapping. Normally that’s quite simple but in D3 most solutions offered by the various examples consisted of a complex function which looped through the data, I gave up in the end and truncated the string before returning to the problem later to resolve it with a different method.
What I had to do was create a new SVG foreign object over the node and add the text to that using a HTML <P> tag which allowed me to easily style it using a class.
nodeposs = svg.append(“g”).selectAll(“#fo”)
    .data(graph.nodes)
    .enter()
    .append('foreignObject')
    .attr("class", "nodetext")
    .attr('style', 'display: flex;justify-content: center;align-items: center;text-align:center;vertical-align:middle;padding:2px;margin:2px;');

nodename = nodeposs.append('xhtml:p')
    .text(function(d){return d.Name;});
Next was to thicken and darken the path lines to show the volume.

Network V4

I wanted to use colour to display more information. Firstly I thought the some nodes maybe different actions but belong to the same department. Secondly the arrow could indicate if there was a blockage in the pipeline depending on the SLA of that process. Finally, for even more information for the user,  I added pop ups for the nodes and RAG arrows to display actual values.

Network v5

Code for this version can be found here https://github.com/RichardPearce60/NetworkChart-ProccessFlow-D3, I’d welcome any suggestions people have optimizing the code.

Future Development:

  • Connect the visualization to Qlik Sense as an Extension
  • Allow the user to resize the chart
  • Allow the user to select objects and pass those selection to Qlik
  • Add a further chart in the PopUps to show further information. For example a distribution chart on the RAG arrows.

Again any further ideas for development is very welcome.

Leave a comment