I want to plot multiple countries for which the data comes from individual topoJSON files. The map with these countries should be in the middle of the screen (centered) and the appropriate scale should be set that the map fills up the whole window.
What I've already tried:
To get the bounding box with
path.bounds(d)
for every country and use for every side (top, left, bottm, right) the max and min values respectively and provide the mean center frompath.centroid(d)
toprojection.center()
. This didn't work.To apply
projection.fitExtent([[x0,y0],[x1,y1]],geojsonObject)
orprojection.fitSize([width,height],geojsonObject)
as proposed in this solution. Here I was not able to create the featureCollection as described and use it to create the map.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title></title>
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<style type="text/css">
.svg-container {
display: inline-block;
position: relative;
width: 100%;
padding-bottom: 100%;
vertical-align: top;
overflow: hidden;
}
.svg-content {
display: inline-block;
position: absolute;
margin: 0;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>
</head>
<body>
<div id="container" class="svg-container"> </div>
<script type="text/javascript">
var width = 600; //for simplicity set to fixed value
var height = 600; //for simplicity set to fixed value
var projection = d3.geoMercator();
var path = d3.geoPath()
.projection(projection);
var svg = d3.select("#container").append("svg")
.classed("svg-content", true)
.attr("width", width)
.attr("height", height);
//Example data
var countries = ['germany', 'italy', 'switzerland', 'france'];
function loadJsonFiles() {
var files = ["https://api.myjson.com/bins/1b0ddz",
"https://api.myjson.com/bins/11jkvb",
"https://api.myjson.com/bins/96x1j",
"https://api.myjson.com/bins/sspzr"];
var promises = [];
var allCountryData = [];
files.forEach(function(url) {
promises.push(d3.json(url))
});
return Promise.all(promises)
.then(function(countryData) {
for (var i = 0; i < countryData.length; i++) {
allCountryData.push(countryData[i]);
}
return allCountryData;
});
}
loadJsonFiles().then(function(allCountryData) {
var allBounds = [];
var objName;
var countryData;
for (var i = 0; i < allCountryData.length; i++) {
objName = allCountryData[i].objects[countries[i]];
countryData = topojson.feature(allCountryData[i], objName);
//How can I use the right projection parameters for all country data loaded from topojson (outside the loop)?
projection
.scale(1000) //How to set this programmatically?
.center([8,47]) //How to set this programmatically?
.translate([width / 2, height / 2]);
//How can I append all the country data to the svg (outside the loop)?
svg.append("path")
.datum(countryData)
.attr("d", path);
}
});
</script>
</body>
</html>
I think it should be possible to solve this problem with the suggestion provided by Andrew Reid in this post with fitSize
or fitExtent
. But I was no able to apply this to my problem. This would also be my prefered way to solve my problem.
Alternatively, is it possible to solve this problem with center()
and scale()
?
How would I have to determine which coordinates I have to provide to center()
and the value to scale()
.?
Thanks very much for the help, I tried for days but did not succeed.