4
votes

Hy

I'm trying to draw an svg with d3.v3.js from geojson. I fetch the geojson from openstreetmap(my test data: http://pastebin.com/4GQne42i) and try to render it to svg.

My JS code:

var path, vis, xy, jdata;

    xy = d3.geo.mercator().translate([0, 0]).scale(200);

    path = d3.geo.path().projection(xy);

    vis = d3.select("body").append("svg").attr("width", 960).attr("height", 600);

    //22.json is the name of the file which contains the geojson data
    d3.json("22.json", function(error, json) { 
      jdata = json;
      if(error!=null)
    console.log(error);
      return vis.append("svg:g")
          .selectAll("path")
          .data(json.coordinates)
          .enter().append("path")
          .attr("d", path);
    });

And somehow my svg result is this:

<svg width="960" height="600">
 <g>
  <path></path>
 </g>
</svg>

I know the projection is not good, but I think the svg should have nodes.

What is the problem with my code? Would you post a correct solution?

2

2 Answers

5
votes

The first problem is with your data join:

vis.append("g")
  .selectAll("path")
    .data(json.coordinates)
  .enter().append("path")
    .attr("d", path);

This would mean you want one path element for each element in the json.coordinates array. Since your test data is a polygon, that would mean one path element for the exterior ring, and then perhaps multiple other path elements for any interior holes, if your data has them. I expect you just want a single path element for the entire polygon.

The second problem is that you’re not passing valid GeoJSON to the d3.geo.path instance. Because the data in your data join is json.coordinates, you’re just passing an array of coordinates directly to path, when you need to pass a GeoJSON geometry object or a feature. (See the GeoJSON specification.)

Fortunately both of these problems are easy to fix by eliminating the data join and rendering the full polygon. To add just one path element, just call selection.append:

vis.append("path")
    .datum(json)
    .attr("d", path);

Your projection will probably need adjusting (translate and scale), too. You might find the project to bounding box example useful here.

1
votes

Do you really need to do it with D3?

I would suggest to go with more map oriented libraries like:

Leaflet vector layer has support for GeoJSON and its size is quite compact.

Open Layers is also an option but it's size is quite big.

Here is an example how I have used Leaflet + GeoJSON to display suburb shape http://www.geolocation.ws/s/6798/en