Путь, не отображаемый на графике d3.js TopoJSON
-
22-12-2019 - |
Вопрос
Я пытаюсь нарисовать карту с помощью TopoJSON, поэтому я последовал этому примеру
но у меня ничего не получается нарисовать.
вот что я написал
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<style>
path {
fill: #ccc;
stroke: #fff;
stroke-width: .5px;
}
path:hover {
fill: red;
}
</style>
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>
var width = 960,
height = 500;
var path = d3.geo.path();
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height);
d3.json("tunisia.json", function(error, topology) {
console.log(topology);
svg.selectAll("path")
.data(topojson.feature(topology, topology.objects.governorates).features)
.enter().append("path")
.attr("d", path);
});
</script>
</body>
</html>
После некоторой отладки выясняется, что путь в моем случае добавляется следующим образом:
<svg width="960" height="500">
<path></path>
<path></path>
</svg>
в то время как обычно это должно быть так:
<svg width="960" height="500">
<path d="M183.85631949544694,17.16574961388676L184.64695256075555,18.261986556132797L184.24437929962187,21.436416964644536L184.9109502450185,22.72190753660925L183.42733139583214,23.600229178621248L181.43637647772152,23.38526266060535L162.4858998398068,18.04698631290296L162.95134674943927,16.322885588815097L161.24381018256219,15.20848145955324L160.04585728433227,11.701769628478132L161.0879861841512,10.793553936506555L172.9773901748378,14.256236175137701Z"></path>
</svg>
вот данные, которые я использую:https://raw.githubusercontent.com/mtimet/tnacmaps/master/topojson/tunisia.json
не могли бы вы, пожалуйста, проверить, что я делаю не так
Решение
С вашим файлом json нет никаких проблем.
Проблема, с которой вы столкнулись, заключается в том, что вы не определяете проекцию для вашего d3.geo.path()
это означает, что он возвращается к значению по умолчанию.В соответствии с документацией, приведенной по ссылке выше:
#d3.geo.path()
Создает новый генератор географических маршрутов с настройками по умолчанию:тот самый Альберсуза проекция и радиус точки 4,5 пикселя.
Ваши географические данные относятся к карте Туниса, поэтому проекция Альберсуса не будет содержать никаких координат в вашем наборе данных.Вот почему данные пути в вашем выводе пусты.
Чтобы исправить это, вам нужно определить проекцию.Вы можете сделать это, когда загружаете свои данные, и вы можете использовать d3.geo.bounds()
, проходя в вашем featureCollection
чтобы определить географические границы ваших данных.
var featureCollection = topojson.feature(topology, topology.objects.governorates);
var bounds = d3.geo.bounds(featureCollection);
Затем, исходя из этих границ, вы можете вычислить центр вашей коллекции объектов:
var centerX = d3.sum(bounds, function(d) {return d[0];}) / 2,
centerY = d3.sum(bounds, function(d) {return d[1];}) / 2;
Затем вы можете использовать это для центрирования вашей проекции.Например, если вы используете проекцию меркатора, вы могли бы выполнить следующее:
var projection = d3.geo.mercator()
.scale(3000)
.center([centerX, centerY]);
Выбор шкалы 3000 произволен, просто казалось, что в данном случае она хорошо работает, настройте ее так, как подходит именно вам.
Наконец, вам нужно установить .projection()
из вашего path
к проекции, которую вы сделали, прежде чем фактически создать svg-пути.
path.projection(projection);
svg.selectAll("path")
.data(featureCollection.features)
.enter().append("path")
.attr("d", path);
ЗДЕСЬ это рабочий пример использования ваших данных.