Search code examples
javascriptd3.jssvggeojson

D3 Paths from external data not appearing


I have downloaded a file from OSM and taken a few coordinates to practice loading data from a GeoJSON and writing them into an SVG. Most of the JS code is taken from the maps tutorial by D3Vienno but even though I do not get errors I cannot get anything to appear on screen. Here is the JS file:

window.onload = function(){

var canvas = d3.selectAll("body").append("svg")
    .attr("width", 600)
    .attr("height", 600)

d3.json("test.geojson", function (data){

    var group = canvas.selectAll("g")
    .data(data)
    .enter()
    .append("g")

    var projection= d3.geo.albers();

    var path = d3.geo.path().projection(projection); //.scale(450).translate([0, 1980]);

    var areas = group.append("path")
        .attr("d", path)
        .attr("class", "area")
        .style("stroke-width", 1)
        .style("fill", "none")
        .style("stroke", "steelblue");


});
}

The GeoJSON file has been validated by jsonformatter and I also built a JSFiddle of it to see if that makes a difference.

If I don't comment out the .scale(450).translate([0, 1980]) portion I get a "is not a function error" but it is in the API and I believe it is formatted correctly.

Here is also the HTML:

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <script type="text/javascript" src="http://localhost:8080/d3.min.js"></script>
    <!--<script src="test.geojson"></script>-->
    <script type="text/javascript" src="mapPractice.js"></script>
</head>
<body>

</body>
</html>

If I don't comment out the script tag for the GeoJSON I get "unexpected token error : in the GeoJSON file and this continues to happen until I delete everything but the coordinates, and then I get "Cannot read property 'length' of null" in the D3 file. Sorry for such a multi-part question but I've been trying to understand this problem for days and I just go in circles.


Solution

  • Both, .scale() and .translate() are methods of the d3.geo.projection, not of d3.geo.path(). You probably want something like this:

    var projection= d3.geo.albers()
      .scale(450).translate([0, 1980]);   // Call .scale() and .translate() on the projection!
    
    var path = d3.geo.path().projection(projection);
    

    Furthermore, in your JSFiddle you are binding your data like this:

    var group = canvas.selectAll("g")
      .data(data.coordinates)
    

    Because this will only bind the array of coordinates there is no input to the geo path generator which expects GeoJSON. For the LineString to be rendered you need to bind as this:

    var group = canvas.selectAll("g")
      .data([data])
    

    Examining the SVG's source code you can see, that this does actually insert the path although it will not get rendered because it is to small and off screen. This should give you a good starting point from where to optimize scale and translation to render it the way you need it to.