The mouse is the most common and popular human-computer interaction control found on most desktop and laptop computers. Even today, with multi-touch devices rising to dominance, touch events are typically still emulated into mouse events; therefore making application designed to interact via mouse usable through touches. In this recipe we will learn how to handle standard mouse events in D3.
Open your local copy of the following file in your web browser:
https://github.com/NickQiZhu/d3-cookbook/blob/master/src/chapter10/mouse.html
In the following code example we will explore techniques of registering and handling mouse events in D3. Although, in this particular example we are only handling click
and mousemove
, the techniques utilized here can be applied easily to all other standard mouse events supported by modern browsers:
<script type="text/javascript"> var r = 400; var svg = d3.select("body") .append("svg"); var positionLabel = svg.append("text") .attr("x", 10) .attr("y", 30); svg.on("mousemove", function () { //<-A printPosition(); }); function printPosition() { //<-B var position = d3.mouse(svg.node()); //<-C positionLabel.text(position); } svg.on("click", function () { //<-D for (var i = 1; i < 5; ++i) { var position = d3.mouse(svg.node()); var circle = svg.append("circle") .attr("cx", position[0]) .attr("cy", position[1]) .attr("r", 0) .style("stroke-width", 5 / (i)) .transition() .delay(Math.pow(i, 2.5) * 50) .duration(2000) .ease('quad-in') .attr("r", r) .style("stroke-opacity", 0) .each("end", function () { d3.select(this).remove(); }); } }); </script>
This recipe generates the following interactive visualization:
In D3, to register an event listener, we need to invoke the on
function on a particular selection. The given event listener will be attached to all selected elements for the specified event (line A). The following code in this recipe attaches a mousemove
event listener which displays the current mouse position (line B):
svg.on("mousemove", function () { //<-A printPosition(); }); function printPosition() { //<-B var position = d3.mouse(svg.node()); //<-C positionLabel.text(position); }
On line C we used d3.mouse
function to obtain the current mouse position relative to the given container element. This function returns a two-element array [x, y]. After this we also registered an event listener for mouse click
event on line D using the same on
function:
svg.on("click", function () { //<-D for (var i = 1; i < 5; ++i) { var position = d3.mouse(svg.node()); var circle = svg.append("circle") .attr("cx", position[0]) .attr("cy", position[1]) .attr("r", 0) .style("stroke-width", 5 / (i)) // <-E .transition() .delay(Math.pow(i, 2.5) * 50) // <-F .duration(2000) .ease('quad-in') .attr("r", r) .style("stroke-opacity", 0) .each("end", function () { d3.select(this).remove(); // <-G }); } });
Once again, we retrieved the current mouse position using d3.mouse
function and then generated five concentric expanding circles to simulate the ripple effect. The ripple effect was simulated using geometrically increasing delay (line F) with decreasing stroke-width
(line E). Finally when the transition effect is over, the circles were removed using transition end
listener (line G). If you are not familiar with this type of transition control please review Chapter 6, Transition with Style, for more details.
Although, we have only demonstrated listening on the click
and mousemove
events in this recipe, you can listen on any event that your browser supports through the on
function. The following is a list of mouse events that are useful to know when building your interactive visualization:
click
: Dispatched when user clicks a mouse buttondbclick
: Dispatched when a mouse button is clicked twicemousedown
: Dispatched when a mouse button is pressedmouseenter
: Dispatched when mouse is moved onto the boundaries of an element or one of its descendent elementsmouseleave
: Dispatched when mouse is moved off of the boundaries of an element and all of its descendent elementsmousemove
: Dispatched when mouse is moved over an elementmouseout
: Dispatched when mouse is moved off of the boundaries of an elementmouseover
: Dispatched when mouse is moved onto the boundaries of an elementmouseup
: Dispatched when a mouse button is released over an element