У меня есть листовка с географическим указанием c точек с использованием d3. js. Карта считывается в файл JSON и отображается в виде точки на карте.
Я хочу, чтобы карта могла динамически загружаться в различные JSON файлы на основе пользовательского ввода. (По сути, каждый JSON содержит геоданные для другого города). Я понимаю, что могу использовать базу данных, но пока не хочу go этот маршрут.
Вот мой код:
// JSON for NYC
var nyc_events = [{"Address": "200 Varick St, New York, NY 10014", "Artist": "Roll Call", "ArtistImage": "https://photos.bandsintown.com/thumb/172269.jpeg", "Coordinates": [-74.00478, 40.72826], "Date": "Tue Feb 11 2020", "EventDate": "2020-02-11", "Genre": "No genre available", "Time": "8:30 PM", "Venue": "SOB's", "moreBioInfo": "No artist bio available", "otherInfo": "No other event info available"}, {"Address":
// JSON for San Francisco
var sf_events = [{"Address": "220 Ellis St, San Francisco, CA 90014", "Artist": "Young Jeezy", "ArtistImage": "https://photos.bandsintown.com/thumb/172269.jpeg", "Coordinates": [-89.00478, 39.72826], "Date": "Tue Feb 11 2020", "EventDate": "2020-02-11", "Genre": "No genre available", "Time": "8:30 PM", "Venue": "Slim's", "moreBioInfo": "No artist bio available", "otherInfo": "No other event info available"}, {"Address":
//Define data
var sfData = "./data/sf_events.json"
var nycData = "./data/nyc_events.json"
//function to dynamically load in data. Function called with event listeners in readyLeaflet function below.
function changeData(data, parameter) {
d3.queue()
.defer(d3.csv,data, function(d) {
})
.await(readyLeaflet(parameter));
}
//call function to populate map with data
changeData(sfData, sf_events)
function readyLeaflet(eventArray) {
//construct datepicker element
const picker = datepicker(document.querySelector('#datepicker'), {
// Event callbacks.
onSelect: function(instance) {
var instanceSplit = instance.dateSelected.toString().split(" " ,4)
var dayofMonth = instanceSplit[2]
//check if date selected on datepicker is equal to date in JSON data
//if equal, filter JSON data that matches current date
//.........
//.........
//.........
update()
},
onShow: function(instance) {
},
onHide: function(instance) {
},
onMonthChange: function(instance) {
},
// Customizations.
formatter: function(el, date, instance) {
el.value = date.toDateString();
dat = new Date()
},
customDays: ['S', 'M', 'T', 'W', 'Th', 'F', 'S'],
customMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
dateSelected: new Date(), // Today is selected.
startDate: new Date(), // This month.
});
//Build leaflet map
var map = L.map('map')
var gl = L.mapboxGL({
accessToken: token,
style: 'mapbox://styles/mapbox/dark-v8'
}).addTo(map);
var svgLayer = L.svg()
svgLayer.addTo(map);
var svgMap = d3.select("#map").select("svg");
var mapG = svgMap.select('g');
//Add points using d3
eventArray.forEach(function(d) {
d.latLong = new L.LatLng(d.Coordinates[1],
d.Coordinates[0]);
})
var events = mapG.selectAll("circle")
.data(eventArray)
.enter().append("circle")
.attr("class", 'events')
.style("fill", '#ffba00')
.attr("r", 17.5)
//Add event listener. If button clicked, call new data.
//This fails
d3.selectAll("#changeData").on("change", function() {
changeData(nycData, nyc_events)
});
}
Первоначальный вызов changeData () работает очень хорошо и заполняет карту данными, как и ожидалось. Это дает мне следующую ошибку, но карта по-прежнему отображает данные:
d3.v4.min.js:2 Uncaught Error: invalid callback
at Zo.await (d3.v4.min.js:2)
at changeData (main.js:59)
at HTMLDocument.<anonymous> (main.js:62)
Однако вызов changeData (nycData, nyc_events) в функции листовки (с кнопкой прослушивания события #changeData button) полностью завершается неудачей. Я получаю сообщение об ошибке:
Uncaught A datepicker already exists on that element.
Чтобы попытаться решить эту проблему, я добавил $("#datepicker").datepicker("destroy");
в функцию changeData (), чтобы она удаляла средство выбора даты перед вызовом новых данных, но это ничего. Фактически, даже когда я полностью удаляю средство выбора даты из DOM, я получаю серию ошибок:
d3.v4.min.js:2 Uncaught Error: invalid callback
at Zo.await (d3.v4.min.js:2)
at changeData (main.js:59)
at HTMLDocument.
И:
leaflet-src.js:3251 Uncaught Error: Map container is already initialized.
at e._initContainer (leaflet-src.js:3251)
at e.initialize (leaflet-src.js:2370)
Я подозреваю, что я установил динамическая c JSON загрузка в changeData () не работает должным образом. Есть ли лучший / более простой способ выполнить sh, что я пытаюсь сделать? Интуиция подсказывает мне, что ошибка выбора даты - это признак ошибки при попытке динамической загрузки новых данных, а не root проблемы.
Спасибо!