projection.fitSize
и projection.fitExtent
оба принимают один объект геойсон, а не массив объектов геойсон. К счастью, у geojson есть тип объекта, который может содержать столько дочерних объектов, сколько нам нужно: a featureCollection
.
Я вижу, что вы используете топойсон, topojson.feature
возвращает объект геойсон. В вашем случае вы возвращаете коллекцию объектов каждый раз, когда используете топойсон.
Чтобы использовать fitSize / fitExtent, нам нужно создать объект геоджон, который содержит все отдельные объекты, для чего используется коллекция объектов, структура выглядит следующим образом:
featureCollection = {
"type":"FeatureCollection",
"features": [ ... ]
}
Мы могли бы создать коллекцию объектов с чем-то вроде:
var featureCollection = {type:"FeatureCollection","features":[]}
for (var i = 0; i < allCountryData.length; i++) {
objName = allCountryData[i].objects[countries[i]];
countryData = topojson.feature(allCountryData[i], objName);
featureCollection.features.push(...countryData.features)
}
Теперь мы можем передать эту коллекцию объектов в fitSize / fitExtent с помощью
projection.fitSize([width,height],featureCollection);
Что должно выглядеть так:
var width = 400; //for simplicity set to fixed value
var height = 200; //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;
var featureCollection = {type:"FeatureCollection","features":[]}
for (var i = 0; i < allCountryData.length; i++) {
objName = allCountryData[i].objects[countries[i]];
countryData = topojson.feature(allCountryData[i], objName);
featureCollection.features.push(...countryData.features)
}
projection.fitSize([400,200],featureCollection)
svg.selectAll("path")
.data(featureCollection.features)
.enter()
.append("path")
.attr("d",path);
});
svg {
border: 1px solid black;
}
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/topojson.v2.min.js"></script>
<div id="container" class="svg-container"> </div>
Я сохранил ваш код, за исключением того, что я использовал другой цикл for (показанный выше) для создания коллекции объектов и вместо циклического перехода для добавления каждого пути, в котором я использовал выбор ввода. Наконец, я изменил размер и расположение, чтобы он лучше подходил для просмотра фрагментов.