D3 has tools to make basic chart interactivity relatively simple.
Last time, we left off we had a nice little scatter plot or bubble chart here, but it's completely static right now. There's no interaction with it.
You can see here we're creating our circles and then assigning the X and Y positions and the radius based on a couple of scales that we have and then just using the radius directly. To add interaction, D3 actually makes it extremely simple. We can do that by using the "on-method" of the D3 selection object. What we actually have at the end of this method chain is a selection that refers to all of the circles on our chart.
And so, we're just going to tell it .on ['mouseover'] d3.select[this] ", "this" being the bubble that we've moused over. I want you to set the style named fill to red. If we save that file, go over here and refresh the browser we can see we do, in fact, now, have the ability to roll over these items, and get them to turn red but they're not turning back to the original color.
In order to fix that, we're going to go and we're going to add an .on ['mouseout'] method. We'll set the fill style back to teal. Now, you can see that we can actually roll over and roll back out. The things are rest properly. While this technically works, it's not a great approach, because as you start to add complexity to what happens during your interactions you can start to get code that's a little bit messy.
If, for example, we wanted to change the stroke weight when we mouse over one of these items and make it have a thicker stroke, then, we can do that, but we're also going to have to add code to the mouseout handler to undo that, as well, when you roll out of the item. Otherwise, it's going to stay in the wrong state.
A better approach then editing styles directly is to actually just use a separate CSS class. If we go up here to our CSS we can see the .dot class that we have applied to all of our existing circles. We're just going to add a new class called .active. We'll give it a nice magenta fill so that it stands out and then change the stroke weight like we did before.
Now, to actually apply that new class D3 actually offers a really nice method for this sort of thing. It operates on a D3 selection, we'll say "d3.select [this] " to select the item again. Then, we use the classed method, where you pass it the name of a CSS class, and then, either a true or a false flag to tell D3 to either add that class or remove that class from the item.
Now that we have that, we can simply roll over these, add the active class to that item or remove it based on whether we're rolling in or out of the item. The last thing I want to show is something I mentioned previously, which is that these functions that got called in response to these events actually do have a reference to the data item that these bubbles represent. And so, if we copy our existing handlers here, and we'll create a mousedown handler in this case...
You can see we've already got the [d] argument in our function here. What we can actually then do is change our code to instead of updating the style we will actually have it set one of these attributes that are the same attributes that we used in creating the circles to begin with but we'll set it to a new value.
In this case, when we mouse down on an item we're going to set its radius attribute to be the r property of its data object and multiply that by two so it will be twice as large. And then, we'll create a mouseup handler that puts it back to the correct value using the radius directly.
Now, you can see that we can actually click on these items and while our mousedown is on it will increase in size and then it will go back when we release.