How to Get Node Datum on Mouseover in D3 V6

Unable to get node datum on mouseover in D3 v6

D3v5 and earlier

In d3v5 and earlier we could use the pattern:

selection.on("eventType", function(d,i,nodes) { .... })

Where d is the datum of the element triggering the event, i is its index, and nodes the current group of elements. Event information could be accessed within the event listener with d3.event.

D3v6

In d3v6 the pattern has been changed:

selection.on("eventType", function(event, d) { .... })

Now the event is passed directly to the listener as the first parameter, the datum is now the 2nd parameter passed to the listener. As part of this change d3.event has been removed.

As stated in the documentation:

D3 now passes events directly to listeners, replacing the d3.event global and bringing D3 inline with vanilla JavaScript and most other frameworks. (source)

This change applies to brush.on, transition.on, and drag.on, zoom.on as well as selection.on.

this

You can still use d3.select(this) in the event listener function as you did prior to d3v6. However, if using arrow functions, this will have a different scope. In d3v5 and earlier you could use:

(d,i,nodes) => d3.select(nodes[i])...

In d3v6+ you can use (for selection.on()):

(event,d) => d3.select(event.currentTarget)...

Positioning

To get the x,y position of the triggering event, where you would have used d3.mouse(this), you can now use:

d3.pointer(event);

Where you would have used d3.event.x and d3.event.y, in d3v5, you would now use:

event.x, event.y

Example

Below is a simple example of passing the event and the datum to the listener function in D3v6. The snippet uses d3.pointer() to get the x,y properties of the click relative to the SVG. Click on a rectangle to get the rectangle's datum and the x and y properties of the event logged to console:

var svg = d3.select("body")
.append("svg");

svg.selectAll("rect")
.data([1,2,3])
.enter()
.append("rect")
.attr("width",30)
.attr("height",30)
.attr("x", function(d) { return d*50; })
.on("click", function(event, d) {
console.log(d);
console.log(d3.pointer(event));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.0.0/d3.min.js"></script>

D3.js v6.2 - get data index in listener function - selection.on('click', listener)

The Observable notebook on the new features in d3-selection 2.0 suggests using a local variable to preserve the index:

Listeners are no longer passed the selected element’s index (i) or siblings (nodes). These were rarely used, had confusing behavior if elements were re-selected, and could cause memory leaks. If you need them, bake them into the element’s data or use a local variable instead.

This can be done with little effort along the following lines:

let data = [2,5,8,9]

const index = d3.local(); // Local variable for storing the index.

d3.select("body").selectAll("p")
.data(data)
.enter()
.append("p")
.text(d=>d)
.each(function(d, i) {
index.set(this, i); // Store index in local variable.
})
.on("mouseover", function(e,d,i){
console.log(d);
console.log(index.get(this)); // Get index from local variable.
});
<script src="https://d3js.org/d3.v6.min.js"></script>

Hover on data point returns undefined in D3.js line chart

I think you need to adjust your event listeners.

As an example, in the "mouseover" function, the first argument is the mouse event, and there is a second argument which is the data attached to the element that dispatched that event...

.on("mouseover",(event, d)=>{
//check what we're passing to the m_over function
console.log('data:', d);
m_over(d);
})

Here's a really simple example illustrating the concept
https://codepen.io/tomp/pen/wveRNmV

D3 event listeners returning MouseEvent instead the datum

In the latest version, d3 v6, the API for events has changed:

  selection.on("mouseenter", function(event, d) {
const e = selection.nodes();
const i = e.indexOf(this);
console.log(d, i, e);
})

If you want to use the v5 API, use in your HTML:

<script src="https://d3js.org/d3.v5.min.js"></script>

d3.js undefined data value in callback function click event

Replace

group1.on("click",d => console.log(d.value));

with

group1.on("click",(e, d) => console.log(d.value));

Since D3 V6, event is passed as the first argument to the mouse event callbacks

d parameter returns undefined in a .on event

It's because the "click" event gives you the event param first, then the datum:

When a specified event is dispatched on a selected element, the specified listener will be evaluated for the element, being passed the current event (event) and the current datum (d), with this as the current DOM element (event.currentTarget). Listeners always see the latest datum for their element.

Related docs

I think you're looking for this:

const countries = [
{
location: 'USA',
},
{
location: 'Canada',
}
];

const buttons = d3.select("body")
.selectAll('button')
.data(countries)
.enter()
.append("button")
.text((d) => { return d.location; }) // returns name location
.attr("value", (d) => { return d.location; }) // returns name location
.on("click", (e, d) => { console.log(d.location) }); // returns name location

Related Codepen

d3 why on mousehover field is undefined and d3.event is undefined too?

There are a couple of problems. First, you have the order of the parameters swapped in your event listener. The first parameter is the event and the second parameter is the datum. Second, rather than d3.event.pageX and d3.event.pageY, you can use event.pageX and event.pageY.

Here's an example:

  .on("mouseover", (event, d) => {
tooltip.style("opacity", .7)
.style("left", (event.pageX + 3) + "px")
.style("top", (event.pageY + 5) + "px")
.html(d.area + "%");
})
.on("mouseout", (event, d) => {
tooltip.style("opacity", 0)
})

D3 Tooltip issues with displaying d on hover

Try below:

chart.selectAll("rect").on("mouseover", function(event, d){ 
return tooltip.style("visibility", "visible")
.text(d.name + " - " + d.calories + " cal");
})

I see two mistakes:

  1. When you assign mouseover event, you need to do it on each rect, not on chart. So chart.selectAll("rect").on part fixes it.
  2. mouseover handler function's first argument is event not data. The second one is data. So you need to do function(event, d) instead of function(d)

Here is the updated example: https://codepen.io/cypark/pen/NWrdpzd



Related Topics



Leave a reply



Submit