score:1

Accepted answer

You are not projecting your line:

var linepath = svg.append("path")
  .datum(data)
  .attr("d", line)
   .attr('class', 'line');

In this case your longitude/latitude pairs in your geojson are converted to straight pixel coordinates:

var line = d3.line()
    .x(function(d) { return (d.lon); })
    .y(function(d) { return (d.lat); })
    .curve(d3.curveBasis);

As svg coordinates start at [0,0] in the top left, and your points appear to be around 10 degrees east or so (positive longitude), and 50 degrees north or so (positive latitude), your first point in the line appears 10 pixels from the left and 50 pixels from the top. Also, because svg y values increase as one moves down, but latitude values increase as one moves north (typcally up on a map), your line also appears inverted on the y axis compared to your points.

You could set your line function to use a projection to set the x and y points:

var line = d3.line()
    .x(function(d) { return projection([d.lon,d.lat])[0] ; })
    .y(function(d) { return projection([d.lon,d.lat])[1]; })
    .curve(d3.curveBasis);

You need both latitude and longitude to project a point, so the projection function takes both, and returns both x and y, hence the [0] and [1], this is why your commented out sections don't work

But this is unnecessary, you can pass geojson straight to the path (the same as you do for the world background), that is if your data is available in geojson (though it is not hard to make a geojson on the fly):

var linepath = svg.append("path")
  .datum(data) // in geojson form
  .attr("d", path)  // use your path 
  .attr('class', 'line');

This is more accurate than a line - the segments between lines in a d3.line are straight or follow a predefined curve, in Cartesian coordinate space. A d3.geoPath follows great circle distance, so the segments between points follow the shortest path on the planet, a more accurate representation, thought at times perhaps, less stylistic.

To create the geojson on the fly, assuming your data looks like: [{lon:number,lat:number},{lon:number,lat:number}] you could use something like:

var points = data.map(function(d) { return [d.lon,d.lat] })
var geojson = { "type": "LineString", "coordinates": points }

Related Query

More Query from same tag