With d3.geo.path having a null projection due to TopoJSON already being projected, it can be displayed without any additional transformation. My goal is to plot data in the format of [longitude, latitude] on a map.
Here is a simplified version of my code:
var width, height, path, svg;
width = 960;
height = 600;
path = d3.geo.path().projection(null);
svg = d3.select('.viz').append('svg')
.attr('width', width)
.attr('height', height);
d3.json("counties.json", function(error, us) {
svg.append('path')
.datum(topojson.mesh(us))
.attr('d', path);
});
svg.selectAll('.pin')
.data(ds) // e.g., ds = {[12.521, 15.312], [616.122,-31.160]}
.enter().append('circle', '.pin')
.attr('r', 3)
.attr('transform', function (d) {
return 'translate(' + path([
d.longitude,
d.latitude
]) + ')';
});
While debugging, I confirmed that the data is fetched properly. However, I encounter an error stating that "path([d.longitude, d.latitude])" is undefined. Both "d" and "path" contain the necessary values. This issue seems related to the null projection.
How can I address this problem?
------- EDIT ------- Following Ben Lyall's suggestion, I removed "path" from the selectAll statement and placed it inside the .json() function. I also corrected the sample data in ds. Below is the updated code.
The map now displays correctly without any console errors, but the circles are not visible on the map itself.
var width, height, path, svg;
width = 960;
height = 600;
path = d3.geo.path().projection(null);
svg = d3.select('.viz').append('svg')
.attr('width', width)
.attr('height', height);
d3.json("counties.json", function(error, us) {
svg.append('path')
.datum(topojson.mesh(us))
.attr('d', path);
svg.selectAll('.pin')
.data(ds) // e.g., ds = [{longitude: 12.521, latitude: 15.312}, {longitude: 616.122, latitude: -31.160}]
.enter().append('circle', '.pin')
.attr('r', 3)
.attr('transform', function (d) {
return 'translate(' +
d.longitude + ',' + d.latitude +
')';
});
});
------- EDIT ------- The solution involved implementing Ben Lyall's suggestion and considering the existing projection for the pins. Since the projection is null in the code, a new one matching the map projection had to be created for the pins' transform. Here is the final solution:
var width, height, path, projection, svg;
width = 960;
height = 600;
path = d3.geo.path().projection(null);
projection = d3.geo.albersUsa().scale(1280).translate([width/2, height/2]);
svg = d3.select('.viz').append('svg')
.attr('width', width)
.attr('height', height);
d3.json("counties.json", function(error, us) {
svg.append('path')
.datum(topojson.mesh(us))
.attr('d', path);
svg.selectAll('.pin')
.data(ds)
.enter().append('circle', '.pin')
.attr('r', 3)
.attr('transform', function (d) {
return 'translate(' +
projection([d.longitude, d.latitude]) +
')';
});
});