简体   繁体   中英

Path not showing in d3.js topoJson graph

I am trying to draw a map using topoJson so I followed this example

but I am not getting anything drawn.

here's what i wrote

<!DOCTYPE html>

<head>
  <meta charset="utf-8">
<style>

path {
  fill: #ccc;
  stroke: #fff;
  stroke-width: .5px;
}

path:hover {
  fill: red;
}

</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>

var width = 960,
    height = 500;

var path = d3.geo.path();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

  d3.json("tunisia.json", function(error, topology) {

  console.log(topology);

  svg.selectAll("path")
      .data(topojson.feature(topology, topology.objects.governorates).features)
      .enter().append("path")
      .attr("d", path);
});

</script>

</body>
</html>

After some debugging it turns out that the path in my case is added as follows:

<svg width="960" height="500">
<path></path>
<path></path>
</svg>

whereas it should normally be like this:

<svg width="960" height="500">
 <path d="M183.85631949544694,17.16574961388676L184.64695256075555,18.261986556132797L184.24437929962187,21.436416964644536L184.9109502450185,22.72190753660925L183.42733139583214,23.600229178621248L181.43637647772152,23.38526266060535L162.4858998398068,18.04698631290296L162.95134674943927,16.322885588815097L161.24381018256219,15.20848145955324L160.04585728433227,11.701769628478132L161.0879861841512,10.793553936506555L172.9773901748378,14.256236175137701Z"></path>
</svg>

here is the data I am using: https://raw.githubusercontent.com/mtimet/tnacmaps/master/topojson/tunisia.json

could you please check what I am doing wrong

There is no problem with your json file.

The issue you are having is that you are not defining a projection for your d3.geo.path() which means it falls back to the default. According to the documentation linked above:

#d3.geo.path()

Creates a new geographic path generator with the default settings: the albersUsa projection and a point radius of 4.5 pixels.

Your geo data is for a map of Tunisia, so an albersUsa projection won't contain any of the coordinates in your dataset. That is why the path data is empty in your output.

To fix this, you need to define a projection. You can do this when you load your data, and you can use d3.geo.bounds() , passing in your featureCollection to find the geographic boundaries of your data.

var featureCollection = topojson.feature(topology, topology.objects.governorates);
var bounds = d3.geo.bounds(featureCollection);

Then from these boundaries, you can calculate the center of your featureCollection:

var centerX = d3.sum(bounds, function(d) {return d[0];}) / 2,
    centerY = d3.sum(bounds, function(d) {return d[1];}) / 2;

Then you can use this to center your projection. For example, if you're using a mercator projection, you could do the following:

var projection = d3.geo.mercator()
  .scale(3000)
  .center([centerX, centerY]);

The choice of a scale of 3000 is arbitrary, it just seemed to work well in this case, tweak it to whatever works for you.

Finally, you need to set the .projection() of your path to the projection you made, before actually creating the svg paths.

path.projection(projection);

svg.selectAll("path")
  .data(featureCollection.features)
  .enter().append("path")
  .attr("d", path);

HERE is a working example using your data.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM