Reputation: 637
I am currently having trouble trying to display country names on a d3 world map.
Here is an image of a leaflet example which shows country names. This would be something I would like to add to my d3 version. JUST the country names if possible. If not I can always go the leaflet route but thought I'd try in d3 first.
Here is the d3 version
Here is how I am currently drawing the map
// reference to actual element d3 selects
this.svg = d3.select(this.mapContainer.nativeElement)
.append('svg')
.attr('width', this.width)
.attr('height', this.height)
.call(zoom)
.append('g')
.attr('class', 'map');
this.projection = d3.geoMercator()
.scale(225)
.translate([this.width / 2, this.height / 1.5]);
const path = d3.geoPath().projection(this.projection);
let g = this.svg.append('g');
// if unknown is not in the filter set remove it from the json
const filteredWorldMapJson = this.worldMapJson.features;
// features are a list of countries
// ex: { type: 'Feature', properties: { name: 'United States }, geometry: { type: 'Polygon', coordinates[] }, id: 'USA' }
let test = g.attr('class', 'countries')
.selectAll('path')
.data(filteredWorldMapJson)
.enter()
.append('path')
.attr('d', path)
.attr('class', d => d.id)
.style('fill', d => this._mapService.getBinColor(d.id))
.style('stroke', 'white')
.style('opacity', 0.8)
.style('stroke-width', 0.3);
// id = countries abbreviation
this.svg.append('path')
.datum(topojson.mesh(filteredWorldMapJson, (a, b) => a.id !== b.id))
.attr('class', 'names')
.attr('d', path);
The country names are part of the geojson so I assume I can grab that and append them to each country somehow
Upvotes: 1
Views: 3658
Reputation: 1927
Good question - in general, you want to parse the label data (in this case country names) out of your geojson file and use the projected position of the the geographic feature the label belongs to to position the label on the map.
here's some code that does this:
// Filter down the labels by label rank (only show the most important labels)
var labelData = data.features.filter(function(d) {
return d.properties.labelrank < 4;
});
var labels = grp.selectAll('text.label').data(labelData);
labels
.enter()
.append('text')
.classed('label', true);
labels
.attr('x', function(d) {
return projection(d3.geo.centroid(d))[0];
})
.attr('y', function(d) {
return projection(d3.geo.centroid(d))[1];
})
.attr('text-anchor', function(d, i) {
// Randomly align the label
var idx = Math.round(3 * Math.random());
return ['start', 'middle', 'end'][idx];
})
.text(function(d) {
return d.properties.admin;
});
labels.exit().remove();
full working example here http://blockbuilder.org/pnavarrc/75ec1502f51f86c2f43e
Upvotes: 5