D3 добавляет пути GeoJSON в SVG, но ничего не отображается
Я пытаюсь использовать D3 для отображения карты GeoJSON Сан-Франциско. У меня есть следующие файлы, которые я обслуживаю с помощью "http-server -c-1":
index.html:
<!DOCTYPE html>
<html>
<head>
<script src="http://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script src="./d3Map.js"></script>
</body>
</html>
d3Map.js:
const d3 = window.d3;
// Append a svg to the HTML body and set its height and width:
const svg = d3.select('body')
.append('svg')
.attr('height', 500)
.attr('width', 500)
// Append the <g> element which is used for grouping SVGs:
const g = svg.append('g');
// Get the GeoJSON data and use it to setup the paths:
d3.json('./sfmaps/neighborhoods.json', (error, topology) => {
// Setup the projection:
const bounds = d3.geoBounds(topology);
const centerX = d3.sum(bounds, (d) => d[0]) / 2;
const centerY = d3.sum(bounds, (d) => d[1]) / 2;
const projection = d3.geoMercator()
.center([centerX, centerY]);
// Create a geographic path generator and set its projection:
const path = d3.geoPath()
.projection(d3.geoMercator());
g.selectAll('path')
.data(topology.features)
.enter()
.append('path')
.attr('d', path);
});
Когда я проверяю полученную страницу, у меня есть:
<body>
<svg>
<g>
<path d="..."></path>
<path d="..."></path>
...
</g>
</svg>
</body
Однако отображаемый SVG пуст.
Я подозревал, что проекция не была правильно масштабирована или отцентрирована, поэтому я попытался опустить.center(...), центр жесткого кодирования с широтой и долготой для Сан-Франциско и использовать.fitSize(...).
Я немного смущен терминологией документации. Когда он говорит, что значение должно быть объектом GeoJSON, я не уверен, означает ли это, что это должен быть весь JSON (то, что я назвал "топологией" в моем коде), функции (topology.features) или отдельный путь (топология)..features[0]). Тем не менее, я пытался использовать все три, и ни один из них не работал или отображал ошибку в консоли.
Файл GeoJSON был создан кем-то другим, поэтому я уверен, что он правильный.
Есть ли у вас какие-либо предложения по поводу того, что я могу делать неправильно или какие пути я должен использовать для устранения этого?
1 ответ
Два вопроса:
- Применение проекции
Вы устанавливаете проекцию
const projection = d3.geoMercator()
.center([centerX, centerY]);
Но тогда вы не используете его:
const path = d3.geoPath()
.projection(d3.geoMercator()); // applies default mercator
Пытаться:
const path = d3.geoPath()
.projection(projection); // applies mercator with modified parameters
- Переведите свою проекцию
Перевод по умолчанию для проекции d3, как правило, [480,250], который помещает координату центрирования в середину SVG, которая составляет 960 пикселей на 500 пикселей. Ваш svg 500 х 500, поэтому вы должны использовать:
projection.translate([250,250])
Что касается вашего вопроса об объектах геойсон. Объект Geojson может быть либо коллекцией объектов (topology
переменная в вашем коде) или конкретный объект / форма в наборе функций набора объектов: topology.features[0]
, но это не может быть массив, как topology.features
, Это просто должен быть действительный одиночный объект geojson, см. Больше, чем вы когда-либо хотели знать о geojson для получения дополнительной информации о действительных объектах geojson.
При передаче объекта geojson, такого как коллекция объектов, в fitSize, ваш код может выглядеть следующим образом:
projection = d3.geoMercator()
.fitSize([width,height],topology)
Обратите внимание, что это не меняет координату центрирования, но переводит и масштабирует элемент карты, чтобы соответствовать указанным размерам. Если вы используете этот метод, вам не нужно указывать перевод, так как этот метод определяет сам перевод.
Если указать координату центра с .center([long,lat])
(и не используя fitSize), тогда вам нужно будет указать перевод, как в пункте 2 выше.
Последнее замечание:
Geojson не кодирует топологию, формат topojson записывает топологию объектов. При обработке с помощью topojson.js топойсон преобразуется в геойсон. В качестве имени переменной использование топологии подразумевает использование топойсона, а не геойсона.