Я работаю над проектом с использованием D3.JS и Flask, пытающихся отобразить карту США. Проблема в том, что карта не отображается. Я знаю, что элемент SVG привязан, что данные json проходят, но сама карта не подходит. Затем я попытался создать простой документ index.html и поместил json файл в этот проект, и с помощью простого Python-сервера можно было увидеть карту. Итак, теперь для кода.
Для начала здесь JS-код:
<script type="text/javascript">
//Define default path generator
let path = d3.geo.path();
//Creating the SVG element and attaching it to the page.
let svg = d3.select("#us-map")
.append("svg")
.attr("width", 900)
.attr("height", 700);
//This function will get the data for the map of the U.S
d3.json("/json", function(json){
console.log(json.features) //This shows an array of 52 objects
//Bind data and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path);
});
</script>
Код Python:
@app.route("/json")
def json():
data = Data()
data_file = data.convert_json_for_d3()
#return data_file
return data_file.to_json()
Метод в классе, который я вызываю из приведенного выше кода:
def convert_json_for_d3(self):
self.__data = pd.read_json('us-states.json')
df = self.__data
return df
HTML:
<section id="us-map">
<h1>UFO Sitings in the U.S.</h1>
</section>
Я работаю над этим уже целый день. Сначала получение данных json, работающих с D3, было сложной задачей. Я подумал, что у меня это было в тот момент. Однако, как я уже сказал, карта не появляется. Он работает, если я помещаю его в простой файл index.html вместе с json. Так что мне интересно, стоит ли проблема с Flask? Один последний момент, я следую по коду из книги "Интерактивная визуализация данных для Интернета". Репозиторий github, который я вытаскивал, приведен здесь: https://github.com/alignedleft/d3-book/blob/master/chapter_12/01_paths.html
Работая с простым файлом HTML, данные отображаются следующим образом:
object {type: "FeatureCollection", features: Array(52)}
features:Array(52)
0:Object
geometry: Object
coordinates: Array(1)
0: Array (33)
0
1
:
1:Object
:
Data in my Flask Project looks like this:
Object {features: Object, type: Object}
features: Object
0: Object
geometry: Object
coordinates: Array(1)
0: Array (33)
0:Array(2)
1: Object
:
Таким образом, и массив объектов почти идентичен, за исключением самой первой строки.
Спасибо за любую помощь.
Два вопроса (на основе комментариев ниже и обновленного вопроса)
Один из них - проект geojson в вашем проекте Flask. Например, функции должны быть массивом, а не объектом, тип все равно должен быть featureCollection (это обсуждается в комментариях ниже). Где-то вдоль линии ваша структура geojson изменяется на то, что не принято d3.geo.path() как действительный geojson.
Во-вторых, вы не используете проекцию для преобразования ваших пар широты и долготы (в геометрии каждой функции) в координатное пространство svg.
По второму вопросу:
При использовании d3.geo.path();
вам нужно указать проекцию (например: d3.geo.path().projection(d3.geo.mercator());
). Если вы не обеспечиваете проекцию, используется нулевая проекция. Это интерпретирует предоставленный geojson без применения каких-либо преобразований - по существу ваши значения переводятся в значения пикселей на svg.
Соединенные Штаты находятся в западном полушарии, поэтому все долготы являются отрицательными (и по мере того как северный юг географические значения возрастают, так как один идет на север, а значения svg
y возрастают по мере того, как один движется вниз, изображение будет перевернуто). Нулевая проекция (без другого преобразования на svg
) будет рисовать путь, который находится слева от ваших границ svg
. Вот почему эти три вещи могут случиться:
Геоисон, упомянутый в главе, на которой вы ссылаетесь, представляет собой непроектированные данные - он содержит пару широт и долготу для каждой вершины: [-133.05341,56.125739]
. Это идеально, так как d3.geo.projection берет этот тип координат, точки на трехмерном эллипсоиде и проектирует их на двумерную декартову плоскость. Если у вас уже есть плоские данные, вам нужно будет использовать геоинформацию.
Таким образом, чтобы визуализировать ваши данные, вам нужно будет выбрать проекцию для преобразования пар широты и долготы в соответствующие значения. Американские альберсы могут быть самыми легкими, поскольку это сложная проекция, которая уменьшает Аляску и перемещает как Аляску, так и Гавайи ближе к континентальным США. Albers USA также устанавливает все параметры проецирования, чтобы показать США без изменения параметров проецирования (центр, поворот, параллели, масштаб и т.д.), В то время как для других прогнозов потребуется установка правильных параметров.
Я получил ваши данные для отображения с проекцией albersUsa, используя следующий код:
var projection = d3.geo.albersUsa().translate([width/2,height/2]);
var path = d3.geo.path().projection(projection);
d3.json("us.json",function(data) {
svg.append("path")
.datum(data)
.attr('d',path)
.attr('fill','steelblue')
.attr('stroke','black');
});
Вот рабочая демонстрация и скриншот:
Если ваша карта слишком велика для вашего svg (или наоборот), вы можете установить масштаб с помощью projection.scale(n), при меньшем увеличении числа, увеличьте масштаб.