zachvac zachvac - 3 months ago 11
Javascript Question

D3 - Identifying element by data

I'm learning d3, and so far I have a basic app that shows a US map and as the user mouses over a state it adds text. What I want to do is also have the state turn a different color when moused over. What I have so far:

var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 500);
d3.json("/HelloWorld/data/states.json",function(data){
var projection = d3.geo.albersUsa().translate([250,250]).scale(650);
var path = d3.geo.path().projection(projection);
svg.selectAll("path")
.data(data.features)
.enter()
.append("path")
.attr("d",path)
.attr("fill","red")
.attr("stroke","blue")
.on("mouseover",function(d,i){
d3.select("body").append("text").html("</br>"+d.properties.NAME);
});
});


The problem is although I can refer to the data with d, I need to be able to refer to the path object in order to change the fill attribute, and I'm not sure how to get from the data to the actual HTML element.

Thanks.

Answer

The this keyword refers to the data element being moused over. From the docs:

When a specified event is dispatched on a selected node, the specified listener will be evaluated for each selected element, being passed the current datum (d), the current index (i), and the current group (nodes), with this as the current DOM element. Listeners always see the latest datum for their element, but the index is a property of the selection and is fixed when the listener is assigned; to update the index, re-assign the listener. To access the current event within a listener, use d3.event.

So, just do:

.on("mouseover",function(d,i){
    d3.select("body")
      .append("text")
      .html("</br>"+d.properties.NAME);
    d3.select(this)
      .style("fill", someAwesomeColor);
});

To get the "next" element from the one you mouseover do:

.on("mouseover",function(d,i){
    d3.select(originalSelection.nodes()[i + 1])
      .style("fill", someAwesomeColor);
});

Where originalSelection is the initial selection you call .data on. Note, .nodes is only available in d3 version 4.