web_network_visualization

by Josue Reyes and Lihan (Neil) Zhu

Introduction

This tutorial will walk through the steps of building an interactive network visualization of different types of beer and their relationships to each other.

We used Jose Christian's code to build our visualization. It's a great starting point if you're interested in better understanding how a very simple network is created in D3.

Take a look at the final project and explore its functionality. The beer visualization illustrates how most beers descend two common parents: Ales and Lagers. The nodes represent different beer families. You can click on a node to see which glasses that beer should be served in. You can also hover over each glass to see which beers should be served in that particular glass.

We'll start out with some code and work our way towards the final project.

You don't need to be an expert in web development to get started with a network visualization in D3 however, we do make some assumptions about our audience.

We assume that:

Download the Code

Beer Project

Inside the folder, we have 3 files and 3 folders:

  1. index.html: This is the base code you will use to write your functions.
  2. beerData.json: The dataset used by D3.
  3. style.css: Our CSS file
  4. beer-glasses-icons: A folder containing icon images needed in the program.
  5. Final Project: A folder containing the final version of index.html where we have coded 4 functions to have interactive effects.
  6. Data: A folder containing the python script and CSV used to create our JSON file

Typically, you'd be able to right click on the index.html file and open it with a web browser to render the webpage. If you try this, you'll likely notice that D3 doesn't render. This is because we need a server to run D3.

Running a Local Server on your computer

  1. Open your terminal(Mac) or Command Prompt(Windows).
  2. Cd into the dir your html is currently at. For example: cd Desktop/Beer-Project
  3. Enter:python -m SimpleHTTPServer 8000

Now you're ready to render the HTML files. Click on local host to render the initial file. Open up the index.html file in your preferred text editor. We'll be adding functions, starting at line 235, to this file throughout this tutorial.

Let’s start coding functions

We provide you all the code for each of the four functions. Feel free to copy and paste the code directly into your index.html file or try to write it yourself to better understand what’s going on. We provide detailed comments along the way to help you understand exactly what’s happening at each step. Keep in mind that JavaScript does not require you to indent, but indenting will make your code more readable (so indent!).

mouseoverNodes()

With so many beers, it can be hard to read each label. Everytime we hover over a node on the network, we'll want to highlight it in green and enlarge the font to make the beer name more visible.

In our mouseoverNodes() function we use the D3 selector to select the circle our cursor hovers on.

// Step1: mouseover to highlight the node itself
  // Step1.1: highlight the circle
  d3.select(this).select("circle")
  .transition()
  .duration(50) //the amount of milliseconds the element transitions last
  .style("fill","#99fd17") //makes the circles of the nodes glow green on mouseover
  .attr("r", function(d) { //creates a function to return the radius (r) of the circle on mouseover

  //groups represent the hierarchy of the different beer types
    if (d.group == 1){ //group 1 represents the Ale or Lager, the earliest ancestor node
      return 52; // since group 1 is the our earliest ancestor, the radius should be the largest

    } else if (d.group == 2){
      return 15;

    } else if (d.group == 3){
      return 10;

    } else if (d.group == 4){
      return 8;

    } else if (d.group == 5){
      return 5;

    } else {
      return 1;
    }
  });
//Step1.2: highlight the text
d3.select(this).select("text") //we can add effects to the text on mouseover too
.style("font-size","100%") //the '100%' changes the text to the default font-size. All labels are the same size.

Now reload your code to explore the new interactivity you’ve just added.

mouseout() - V1

You might have noticed that each node you hover over, stays highlighted when you mouse out. We want to return the nodes back to their original appearance each time we mouse away from them. To do this, we'll create the first version of the mouseout function.

mouseoverGlass()

We're going to be adding a mouse over effect to each beer glass icon so that they appear to fill up and so that they can highlight which beers in the network should be served in that particular glass. The mouseoverGlass function will also add the effect of filling the glass with beer each time we hover over it.

mouseout() - V2

Similar to our first issue with the nodes, the glasses remain filled when we mouse away. Let's add functionality to our original mouseout function to also return the glasses to their pre-hovered state.

clickNodes()

Now that we have a good amount of interactivity in our visualization, let's finish by adding a click function to the nodes that will both highlight ancestral nodes for easier visibility, and fill up the corresponding glasses. Remember, each node represents a green circle with a beer name.

for(i = clickedGroup; i > 1; i –){ //loops through the group number (represents hierarchy) from the clicked node to its highest-level parent, whose group is 1 glowId = json.links[glowId - 2].source_id; //based on how parental nodes are connected to the children nodes in the dataset, we get the ID of the parental node accordingly //console.log(json.links[glowId - 2]); //uncomment this if you’re interested in better understanding how child nodes are connected to parent nodes glowIdList.push(glowId); //adds the ID of each parental node into the glowIdList }

  - Step 7.3: Activate (effects color and size) every node (circles and texts) in the array
```javascript
//Step7.3: activate (effects color and size) every node (circles and texts) in the array
for(var i = 0; i < glowIdList.length; i++){ //loops through the IDs in the glowIdList we built in step 7.2
  var selector = "[sourceID='" + glowIdList[i] + "']"; //creates a variable to store the ID of the node

  d3.select(selector).select("circle") //selects the node with the ID of the node stored in the selector variable
  .transition()
  .duration(50)
  .style("fill","#99fd17")
  .attr("r", function(d) { 
    if (d.group == 1){
      return 52;

    } else if (d.group == 2){
      return 15;

    } else if (d.group == 3){
      return 10;

    } else if (d.group == 4){
      return 8;

    } else if (d.group == 5){
      return 5;

    } else {
      return 1;
    }
  });

  d3.select(selector).select("text")
  .transition()
  .duration(50)
  .style("font-size","100%")
}

And you’re done!

Reload your code and explore the new functionality you’ve added.