Вопрос или проблема
Я пытаюсь отобразить карту конгрессионных границ с использованием d3. Мне удается сделать это с обычным файлом geojson, но поскольку он довольно большой, я попытался его сократить с помощью geo2topo. Теперь, когда я пытаюсь отобразить файл topojson в d3 с помощью метода API topojson.feature(), и затем передаю новый возвращаемый сборник функций, он отображает только некоторые геометрии, но не все. Я проверил файл topojson на https://geojson.io/, где он отображается правильно. Поэтому я сейчас немного растерян, что делать.
<!DOCTYPE html>
<div id="container"></div>
<script src="d3.v7.js"></script>
<script src="https://d3js.org/topojson.v1.min.js"></script>
<center>
<div id="map"></div>
</center>
<style>
#map {
margin: 10px;
}
</style>
<script>
const longitude = -96;
const latitude = 39;
const scaleValue = 1000;
const width = 960;
const height = 640;
// функции для увеличения
function zoomFunction(event) {
d3.selectAll("path")
.attr("transform", event.transform);
d3.selectAll("circle")
.attr("transform", event.transform);
}
var zoom = d3.zoom()
.scaleExtent([.6, 7])
.on("zoom", zoomFunction);
// Загрузка файлов и затем вызов функции рендеринга
function loadFiles() {
// загрузка всех файлов здесь
const mapDataPromise = d3.json('assets/2002usaSIMPLE.topo.json');
// Используйте Promise.all, чтобы дождаться завершения всех обещаний для каждого файла
Promise.all([mapDataPromise])
.then(([data]) => {
const data2 = topojson.feature(data, data.objects["2002usa"])
// Отобразите график с обоими наборами данных
renderChart(data2);
})
.catch(error => {
console.error('Ошибка загрузки файлов:', error);
});
}
// Фактическое рендеринг карты
function renderChart(data) {
const projection = d3.geoAlbersUsa()
.scale(scaleValue)
.translate([width / 2, height / 2]);
const pathGenerator = d3.geoPath().projection(projection);
const svg = d3.select("#map")
.append("svg")
.attr("width", width)
.attr("height", height)
.style("border", "2px solid black");
const innerSpace = svg
.append("g")
.attr("class", "inner_space")
.call(zoom);
var usaSVG = innerSpace
.selectAll(".feature")
.data(data.features)
.enter().append("path")
.attr("class", "feature")
.attr("d", pathGenerator)
.attr("fill", "lightblue")
.attr("stroke", "blue")
.on("error", (error) => console.error("Ошибка рендеринга функции:", error)); // Логирование ошибок рендеринга;
}
loadFiles();
</script>
Я пытался проверить, не приводит ли вызов API преобразования topojson -> geojson к поврежденному geojson файлу, но, похоже, он не поврежден, потому что я могу загрузить его на mapshaper.org.
Ответ или решение
При работе с отображением карт в D3.js с использованием TopoJSON может возникнуть проблема, когда некоторые геометрические объекты не отображаются, несмотря на то что они корректно визуализируются в других инструментах, таких как geojson.io. Это может быть вызвано несколькими причинами. Давайте рассмотрим основные из них и решения.
Причины и решения:
-
Ошибки в структуре TopoJSON:
Убедитесь, что объект, который вы передаёте вtopojson.feature()
, действительно содержит все необходимые ключи и леттерную структуру. Проверьте, правильно ли вы указали название объекта, например:const data2 = topojson.feature(data, data.objects["2002usa"]);
Убедитесь, что ключ "2002usa" существует в
data.objects
. Если в вашем TopoJSON находится более одного объекта, нужно убедиться, что вы используете правильный ключ. -
Геометрические объекты отсутствуют:
Иногда в TopoJSON могут отсутствовать некоторые объекты (например, если они были "сжаты" или отфильтрованы при преобразовании). Вы можете проверить количество объектов, вернувшихся отtopojson.feature()
, чтобы убедиться, что они все загружены:console.log(data2.features.length);
Сравните это количество с количеством объектов в исходном GeoJSON.
-
Проблемы с проекцией:
Убедитесь, что ваша проекция правильно настроена и соответствует данным, которые вы визуализируете. Если ваши TopoJSON данные выходят за пределы видимой области, то они могут не отображаться на графике. Проверьте параметры проекции, такие какscale
иtranslate
. -
Ошибки в рендеринге:
Внутри вашего методаrenderChart
, добавьте обработчик ошибок, чтобы увидеть, если какие-то пути не могут быть отрисованы. Вы уже добавили следующий код:.on("error", (error) => console.error("Error rendering feature:", error));
Это хорошо, но в D3 v6 и выше вы можете использовать следующую конструкцию для отладки:
.each(function(d) { const path = pathGenerator(d); if (path == null) { console.error("Path could not be generated for:", d); } });
-
Ошибки в стилях:
Убедитесь, что ваши стили (например,fill
иstroke
) правильно применяются ко всем элементам. Иногда они могут быть скрыты из-за стилей CSS или других факторов.
Итог:
Убедитесь, что входящие данные корректны и полностью загружены, а также что правильные методы и параметры проекции используются. Проверьте логи в консоли для выявления возможных ошибок при рендеринге. Вот набор практических шагов, к которым вы можете обратиться для диагностики и устранения проблемы.
Если эти стратегии не решают вашу проблему, возможно, стоит создать новый минимальный пример, чтобы изолировать проблему, или поделиться конкретными данными с сообществом для получения дополнительной помощи.