Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unable to get node datum on mouseover in D3 v6

Tags:

I am trying to get a nodes' bound datum with selection.on() in D3 v6. In my event listener I'm getting the mouse event data instead of the datum. How do I get the datum?

This my code

const data = {         "nodes": [{             "id": "Myriel",             "group": 1         }, {             "id": "Napoleon",             "group": 1         }]};  const nodes = data.nodes.map(d => Object.create(d));  const node = svg.append("g")         .selectAll("circle")         .data(nodes)         .join("circle")         ...    node.on("mouseover",d=>{       console.log(d); //output = MouseEvent       console.log(d.id); //output = undefined   }); 
like image 215
Perumal Samy S Avatar asked Sep 01 '20 18:09

Perumal Samy S


1 Answers

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>

What about i and nodes?

The index and the group of nodes are no longer passed to the event listener function. However, the migration guide does provide examples of how to find the current group of nodes and the index here.

like image 73
Andrew Reid Avatar answered Sep 18 '22 03:09

Andrew Reid