7 Interactivity
Read: IDVW2, Chapter 10 Interactivity
7.1 Binding event listeners to SVG elements
It’s helpful to think carefully about what you want to happen when an event listener is triggered and what information you need. Open Developer Tools and try these in the Console. Note that event management changed in v6 so code written for earlier versions of D3 will not work.
7.1.2 Change an attribute of the element that received the event
.select("line")
d3.on("click", function() {
.select(this)
d3.attr("stroke-width", "10");
; })
In the context of event handlers, “this” is the element that received the event, a.k.a. what you clicked on if it’s a click event. An alternative (\(\geq\) v6, see link above) is to pass the event and access the element with event.currentTarget
:
or
.select("line")
d3.on("click", function(event) {
.select(event.currentTarget)
d3.attr("stroke", "yellow");
; })
7.1.3 Get the value of an attribute of the element that received the event
.select("circle")
d3.on("click", function(event) {
const rad = d3.select(event.currentTarget).attr("r");
.select("text")
d3.text(`The radius is ${rad} pixels.`);
; })
7.1.4 Do something with the data bound to the element that received the event
.select("circle")
d3.data([{s: "red", sw: "15"}])
.on("click", function(event, d) {
.select(event.currentTarget)
d3.attr("stroke", d.s)
.attr("stroke-width", d.sw);
; })
Note that starting with v6, the data is the 2nd parameter to be passed: function(event, d)
. In addition, note that you do not need to pass d
again when accessing the data: for example we use d.s
not d => d.s
.
As in the previous example, d3.select(this)
can be used instead of d3.select(event.currentTarget)
.
Try changing the data value bound to the circle with d3.select("circle").datum("10")
and clicking again.
7.2 Separating the function and event listener
Examples
function goyellow() {
.select(this)
d3.attr("fill", "yellow")
; }
.select("circle")
d3.on("mouseover", goyellow);
7.5 Dependent event listeners
In these examples, the behavior or existence of one event listener depends on another.
7.5.1 Global variable example
Here the circle click behavior depends on the value of the radio button: if the “Move left” radio button is checked, the circle will move left when clicked. If the “Move right” radio button is checked, the circle will move right when clicked.
A global variable is used to keep track of the radio button value. The event listener on the circle conditions the behavior on the value of this global variable.
Click the circle.
Move left
Move right
// global variable keeps track of which radio button is clicked
let action = "left";
.select("div#rad")
d3.selectAll("input")
.on("click", function() { action = d3.select(this).node().value; });
// circle click behavior depends on value of "action"
.select("svg#radio").select("circle")
d3.on("click", function () {
let cx_new;
if (action == "left") {
= +d3.select(this).attr("cx") - 50;
cx_new if (cx_new < 20) cx_new = 20;
else {
} = +d3.select(this).attr("cx") + 50;
cx_new if (cx_new > 280) cx_new = 280;
}.select(this)
d3.transition()
.duration(500)
.attr("cx", cx_new);
; })
7.5.2 Turn off event listener
In this example, the event listeners on the squares are turned on or off depending on the value of the radio button. Event listeners can be removed by setting the behavior to null
.
Click a square.
Red active
Blue active
// movement function
const jump = function () {
.select(this).transition().duration(500)
d3.attr('y', '0')
.transition().duration(500).ease(d3.easeBounce)
.attr('y', '75');
;
}
// initial setup: add event listener to red square
.select("svg#radio2")
d3.select("rect#red")
.on("click", jump);
// switch event listeners if radio button is clicked
.select("div#rad2").selectAll("input")
d3.on("click", function () {
if (d3.select(this).node().value == "blue") {
.select("svg#radio2").select("rect#blue").on("click", jump);
d3.select("svg#radio2").select("rect#red").on("click", null);
d3else {
} .select("svg#radio2").select("rect#red").on("click", jump);
d3.select("svg#radio2").select("rect#blue").on("click", null);
d3
}; })