Reputation: 302
I'm having trouble updating data after binding values to SVG elements using a key in D3.
Here's an illustration. This is a sample CSV file I'm using to track drilling sites in PA.
name,lat,lng,company,production
1,40.543401,-79.162257,Shell,20000
2,40.608186,-79.369354,Shell,40000
3,40.558923,-79.630966,Shell,10000
4,40.431514,-79.466171,Range,25000
5,40.439876,-80.015488,Range,26000
6,42.173455,-80.513306,CNX,30000
7,39.927082,-74.788055,CNX,120000
8,40.045964,-75.10962,Chesapeake,15000
9,40.822611,-77.839508,Chesapeake,16000
I bind this data to g
elements using this code:
d3.csv("data.csv", type, function(error, data) {
wells = chart.selectAll(".well")
.data(data, function(d){ return d.name; }).enter()
.append("g")
.attr("class", "well")
.attr("id", function(d){ return d.name })
.attr("transform", function(d){ return "translate(" + projection([d.lng, d.lat])[0] + "," + projection([d.lng, d.lat])[1] + ")"; } );
wells.append("circle")
.attr("r", 4);
});
Note that the key I'm binding that data on is name
.
Introduce data2.csv, which is practically identical except the unique id is called well
instead of name
, and two of the lat-lng pairs are switched.
well,lat,lng,company,production
100,40.543401,-79.162257,Shell,20000
2,40.608186,-79.369354,Shell,40000
3,40.558923,-79.630966,Shell,10000
4,40.431514,-79.466171,Range,25000
5,42.173455,-80.513306,Range,26000
6,40.439876,-80.015488,CNX,30000
7,39.927082,-74.788055,CNX,120000
8,40.045964,-75.10962,Chesapeake,15000
9,40.822611,-77.839508,Chesapeake,16000
When I rebind data and update, nothing happens.
d3.csv("data2.csv", type, function(error, data2) {
var wells = chart.selectAll(".well")
.data(data2, function(d){ return d.well; })
.transition().duration(1000)
.attr("transform", function(d){ return "translate(" + projection([d.lng, d.lat])[0] + "," + projection([d.lng, d.lat])[1] + ")"; } );
});
When I change well
back to name
in data2.csv
, the animation works find and the two dots transpose. Why do the field names have to be the same?
Upvotes: 1
Views: 64
Reputation: 34288
This is because of how the key
argument to data
function works. From the docs:
... the key function is invoked once for each element in the new data array, and once again for each existing element in the selection.
When it is called on the existing elements (which have data with field name
and not well
), it returns undefined
and no nodes are selected for the update.
There are a couple of ways to correct this:
.data(data2, function (d) { return d.well || d.name; })
. Less code, better for a one-off visualisation.Upvotes: 2