Question

I am a noob with d3.js. I am using topoJSON data to render maps and so far it's been working great. Now I want to overlay some data such as text or circles on top of each country/region and I am hitting a wall. I have code similar to this:

var countries = g.append("g")
    .attr("id", "countries")
    .selectAll("path")
    .data(topojson.feature(collection, collection.objects.countries).features)
    .enter().append("path")
    .attr("d", path)
    .style("fill", colorize)
    .attr("class", "country")
    .on("click", clicked)

which properly renders my map. In order to overlay some circles on it, I do the following:

countries
    .append("circle")
    .attr("r", function(d, i, j) {
      return 10; // for now
    })
    // getCentroid below is a function that returns the 
    // center of the poligon/path bounding box
    .attr("cy", function(d, i, j) { return getCentroid(countries[0][j])[0]})
    .attr("cx", function(d, i, j) { return getCentroid(countries[0][j])[1]})
    .style("fill", "red")

Which is pretty cumbersome (specially the way it accesses the countries array), but it succeeds at appending a circle for each path representing a country. The problem is that the circle exists in the SVG markup, but doesn't show up at all in the document. I am obviously doing something wrong, but I am at a loss of what is it.

Was it helpful?

Solution

The problem is that you're appending the circle elements to path elements, which you can't do in SVG. You need to append them to the parent g elements. The code would look something like this.

var countries = g.selectAll("g.countries")
  .data(topojson.feature(collection, collection.objects.countries).features)
  .enter().append("g")
  .attr("id", "countries");

countries.append("path")
  .datum(function(d) { return d; })
  .attr("d", path)
  // etc

countries.append("circles")
  // etc
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top