点击打开链接
还有mousemove
Visualisation library: D3.js
By Anthony Nosek
D3.js is fast becoming the default standard in data visualisation libraries. In this short tutorial I’ll discuss mouse events and how you can subscribe and use these events in D3. This is not a complicated tutorial so review the text and use the code provided to expand your own D3.js visualisations.
The mouse events I’ll be discussing in this tutorial are:
– mousedown
– mouseup
– click
– dblclick
– mouseover
– mouseout
– mouseenter
– mouseleave
mousedown, mouseup, click
I’ve grouped these three events together as they’re very closely related. These three events are raised when a graphic element is clicked using the mouse and the order which they get raised is very specific as indicated below:
Action: Graphical element clicked
– mousedown, user depresses the mouse button on the element
– mouseup, user releases the mouse button on the element
– click, one mousedown and one mouseup detected on the element
Let’s write a little D3 code to prove the execution order:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
var
svg = d3.select(
"body"
).append(
"svg"
);
var
square = svg.append(
"rect"
)
.attr(
"height"
, 100)
.attr(
"width"
, 100)
.attr(
"x"
, 10)
.attr(
"y"
, 10)
.attr(
"fill"
,
"green"
)
.on(
"mousedown"
, mouseDown)
.on(
"mouseup"
, mouseUp)
.on(
"click"
, mouseClick);
function
mouseDown() {
console.log(
"mouseDown"
);
}
function
mouseUp() {
console.log(
"mouseUp"
);
}
function
mouseClick() {
console.log(
"mouseClick"
);
}
|
This code snippet draws a 100x100px green square on the canvas at position 10,10. I’ve registered themousedown, mouseup and click events to the square so that when it’s clicked using the mouse each event will fire. Each event, when raised (triggered) will output text to the console which will give us an indication of the execution order. Here’s the console output after the square has been clicked:
Notice the order of the events from top to bottom?
As a general rule of thumb the mousedown and mouseup events are more useful than click. Take the following situation when a user depresses the mouse button over a graphical element and then moves the mouse cursor off the element and releases. The element will have only registered the mousedownevent, the converse being true if a user moves over an element and releases an already depressed mouse button. In both of these cases the click event does not get raised.
dblclick
I don’t often use the dblclick (double-click) event. It gets raised when the mouse button is clicked twice in rapid succession and because click events are also raised during a double-click it’s advisable to keepclick and dblclick events separate, i.e. don’t register both for the same graphical element.
mouseover, mouseout
These mouse events are rather self-explanatory however there is something important to note that renders them different to mouseenter and mouseleave which is discussed in the next topic. Themouseover event is raised when the mouse cursor is moved over an element while the mouseout event is raised when the mouse cursor is moved off an element.
Seems pretty straightforward so far so let’s have a closer look using D3 code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
var
svg = d3.select(
"body"
).append(
"svg"
);
var
data = [
{
"name"
:
"Square 1"
,
"x"
: 10,
"y"
: 10,
"height"
: 100 ,
"width"
: 100,
"fill"
:
"green"
},
{
"name"
:
"Square 2"
,
"x"
: 25,
"y"
: 25,
"height"
: 70 ,
"width"
: 70,
"fill"
:
"yellow"
}
]
var
squares = svg.append(
"g"
)
.selectAll(
'rect'
)
.data(data)
.enter()
.append(
'rect'
)
.attr(
'x'
,
function
(d) {
return
d.x })
.attr(
'y'
,
function
(d) {
return
d.y })
.attr(
'height'
,
function
(d) {
return
d.height })
.attr(
'width'
,
function
(d) {
return
d.width })
.attr(
'fill'
,
function
(d) {
return
d.fill })
.attr(
'stroke'
,
'red'
)
.attr(
'stroke-width'
,0)
.on(
'mouseover'
,
function
() {
d3.select(
this
)
.transition()
.duration(500)
.attr(
'stroke-width'
,3)
})
.on(
'mouseout'
,
function
() {
d3.select(
this
)
.transition()
.duration(500)
.attr(
'stroke-width'
,0)
})
|
You might notice that I’ve used a different method to register the mouse events, instead of calling a separate method I’ve written the event function directly inline. There isn’t a preferred way when registering methods however if you wish to reuse the same event on multiple elements you’re best to write a separate method/function. The code shown above will generate the following output:
As you move the mouse over both elements you’ll notice a red border appearing and disappearing. Themouseover event, when raised will create a red border whilst the mouseout event removes the red border. Do you notice how the red border disappears from the green square when you move onto the yellow square? Ask yourself, have I really left the green square? The yellow square resides within its boundaries so there’s conjecture if the mouseout event should be raised whilst theoretically, still being within the boundaries of the green square. This is called event bubbling.
Luckily, if this side-effect isn’t something you want in your visualisation you can make use of themouseenter and mouseleave events which are discussed in the next topic. Read on!
mouseenter, mouseleave
Again, here’s a fun snippet of code to illustrate the mouseenter and mouseleave events:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
var
svg = d3.select(
"body"
).append(
"svg"
);
var
square = svg.append(
"rect"
)
.attr(
"height"
, 100)
.attr(
"width"
, 100)
.attr(
"x"
, 10)
.attr(
"y"
, 10)
.attr(
"fill"
,
"green"
)
.on(
"mouseenter"
, mouseEnter)
.on(
"mouseleave"
, mouseLeave);
function
mouseEnter() {
square.attr(
"fill"
,
"red"
);
}
function
mouseLeave() {
square.attr(
"fill"
,
"blue"
);
}
|
This code snippet draws a 100x100px green square on the canvas at position 10,10. I’ve registered themouseenter and mouseleave events to change the colour of the square which will indicate at which point the event is being raised. Try the code for yourself and see!
The mouseenter and mouseleave events are almost identical to mouseover and mouseout with the only exception they don’t react to event bubbling. This means they see the entire HTML element as one complete block, they don’t react to mouseover or mouseout events being raised within the block.Mouseover and mouseout events make it easy to identify when a mouse has entered a group of elements as they will only get raised when the mouse enters or leaves the parent.
Conclusion
In this tutorial you’ve been introduced to numerous mouse events which you can use in D3 visualisations. Mouse events are raised/triggered as a result of different user interactions. It is advisable to become familiar with the different mouse events available and their intended usage so that you can add an extra dimension to your data visualisations.