0
votes

I am using d3 to render a world map with clickable countries. The countries are from a geojson file, and I have no problems loading a particular continent, region or the entire world, using this site: https://geojson-maps.ash.ms/

However, the data from that site does not have any capitals in their geojson files. So instead I looked at https://www.naturalearthdata.com/, which clearly shows that one should be able to render a region with cities on it. I take their files and convert them to geojson via https://mapshaper.org/, but for some reason I ONLY get cities, as single dots against a blank background. There is not a single map I can find which provides a map of countries with capitals/cities inside country borders.

This leads me to wonder whether I am somehow supposed to combine a geojson file of countries with a geojson file of capitals, and render one on top of the other. In that case, how is that possible? Or is there some other solution? I attach the code where I render my world map (which works fine):

const data = await d3.json("world.geo.json")

var topology = topojson.topology({ foo: data });

const countries = topojson.feature(topology, topology.objects.foo).features

let targetCountries = countries
selectCountry()

svg.selectAll(".country")
    .data(countries) /* binder selectAll till enter() */
    .enter().append("path")
    .attr("class", "country")
    .attr("d", path)
    .on("mouseover", function (d) {
        d3.select(this).classed("targeted", true)
    })
    .on("mouseout", function (d) {
        d3.select(this).classed("targeted", false)
    })
1
How do you add the cities? You've only shown how you add the countries, which apparently load correctly. Also, can you share a sample of your cities file?Andrew Reid
I forgot to add the preceding line: const data = await d3.json("europe.geo.json") This is where the file is added. I can change the file to one of capitals instead, but that simply creates a map with capitals without countries. I would need to render the capitals and the countries, from different files, onto the same svg element, and I don't know how I could do that.Zuzim
You can use Promise.all() to load multiple CSVs at once: stackoverflow.com/questions/21842384/…Hugo Elhaj-Lahsen
You should definitely combine files like that, just like how you selectAll .country, you can also selectAll .capitalRuben Helsloot
Could you please show me a minimally working solution for what you describe, including my code above? I am rather new to this and didn't write all the above code myself. And is it possible to load multiple json files in the same way (I have not encountered csv before)?Zuzim

1 Answers

0
votes

I have a solution now, posting it here in case it helps anyone else:

const data = await Promise.all([d3.json("world.geo.json"), d3.json("capitals_0yl.json")])

var topology = topojson.topology({ foo: data[0], bar: data[1] });

const countries = topojson.feature(topology, topology.objects.foo).features
const cities = topojson.feature(topology, topology.objects.bar).features

let combined = d3.merge([countries, cities])

svg.selectAll(".country")
    .data(combined) /* binder selectAll till enter() */
    .enter().append("path")
    .attr("class", "country")
    .attr("d", path)
    .on("mouseover", function (d) {
        d3.select(this).classed("targeted", true)
    })
    .on("mouseout", function (d) {
        d3.select(this).classed("targeted", false)
    })