# CS465 - Lab 5 Interaction II

# Objectives

  • Incorporate HTML controls and D3
  • Update displayed data
  • Add transitions to animate changes

# Starting the lab

Go to Github Classroom and grab the starter code for the lab.

In this repository, I've given you the basic scatterplot that you had to build in the last lab (though minus some of the features we added in that lab).

# Changing variable encodings on the fly

The first thing we are going to do is to create a control that will allow us to change which variables appear on the two axes.

To do this, we are going to create a drop down menu using the select tag. Take a quick look at the example.

We will create the initial framework in HTML and then populate it using JavaScript. Finally, we will respond to changes by updating the visualization.

Step one Add in the HTML. Place this div into the HTML right after the SVG tag.

<div>
    X Axis: <select id="x_variable"></select>
</div>

Step two Find the names of the variables from the data. After the data is loaded, write a for loop of the form for (prop in data[0]). We are using data[0] as a representative of our dataset. The x in obj syntax tells JavaScript to iterate over all of the properties of obj, setting prop equal to each name in turn. Go ahead and print these out so you can see them.

Step three Populate the menu with the names of our variables. Use D3 to create a selection of #x_variable. Then, for each iteration of the loop, append an option tag to the selection. We need to set the value and the text of each option as it is created (setting both to the name of the variable). Use attr() to set the value attribute to the name of the variable and use the text() function to set the label. We don't really want "class" included, so add an if statement into the loop that skips prop when it is "class".

Step four Add an event handler to the select. At the bottom of your code (but still within the then()), use D3 to select #x_variable, and then use the on() function to create an event handler for the "change" event. On the first line, write const metric = this.value. The variable metric will now hold the current selection. Print this value out to check.

Step five Update the visualization. There are actually a couple of things that we need to do when the variable is changed. We need to update the scale, we need to change the position of the circles and we need to update the axis.

Step five A Change the scale. We don't need to make a whole new scale, all we need to do is to change the domain based on the new metric.

Step five B Change the circle location. Again, we don't need to remake the plot, just change the one thing that needs changing. Use your circles selection and change the encoding for cx.

Step five C Change the axis. Use the x_axis selection to call the axis building code again. It will adjust the axis to fit the new scale.

Step six Make sure that the variable shown in the menu matches the variable actually being shown when the page loads. The best way to do this is to select the select object and then set the property value to your chosen variable. We do this in D3 with d3.select("#x_variable").property("value", "petal_length") (for example).

Step seven Test, test, test.

Step eight Repeat for the Y axis.

# Transitions

Transitions are a special kind of D3 selection. They support most of the functionality of normal selections (attr, style, etc...) except for append. They allow us to change the rate at which things change.

Right now, when you change the encoding of an axis, the circles all snap to the new location. This can make it difficult to keep track of how the change has affected the circles. So, what we do is we add a transition, and then apply the change with that selection. The transition will apply the change gradually, so we can see it happen.

We add a transition by taking an existing selection and calling transition() on it. The result is a transition selection of the same items. In addition to all of the normal selection functions, we have two functions (delay and duration) which can be used to control the transition. The delay() function changes how long a object waits to start changing, and the duration() can be used to set how long the change takes.

Step one Add a transition to the x axis change. In the event handler where you change the cx attribute, insert transition() before the .attr().

Step two Add a duration. After the creation of the transition selection and the call to attr(), insert a call to duration() and give it a number (in milliseconds). Run your code and see the circles slowly glide across the page (provided the number was big enough).

Step three Add a delay. Repeat the same process with the delay. You should now see that it takes a moment before the circles start to move.

Step four Stagger the movement. As it turns out, delay and duration can take numeric values or functions that work just like the function arguments we have given to attr and style -- they are passed the data object and the index of the object as arguments. Use i to stagger the delay by returning i * 5.

Step five Repeat for the y axis.

In this process, we have made something of a mess. We have a lot of duplicated functionality, which leads to all kinds of problems if we want to change something. It is important not to lose sight of the fact that we are still programming and we don't want to lose any of our good software development habits.

Create a pair of new variables which hold the current variables for the two axes. Update these variables when they should change.

Then write a function that sets the domain of both scales, adjusts both axes and sets both the cx and cy attributes (with transition) based on a pair of input parameters (the x and y variables).

Now, work through your code and remove any code that duplicates this functionality and replace it with a call to your new function. So, for example, when you make the scales, you will only set the range. When you create the circles, you only set the radius, etc...

This kind of approach will help you as your code gets more complex.

Last Updated: 10/26/2018, 5:12:48 PM