Я новичок в D3.js, и меня попросили взять на себя проект, который кто-то еще начал работать.
Цель состоит в том, чтобы иметь карту, которая извлекает json-данные для точек, а затем, когда нажимаются точки, открывается диалоговое окно jQuery с правильными json-данными для каждой точки.
Мне удалось получить всплывающее окно jQuery для работы на карте, но каждая точка, которая нажата, заполняется одним и тем же текстом.
Я также тестировал загрузку и отображение json-данных на простой странице html с использованием $.getJSON, и я смог получить это, чтобы полностью обработать все json-данные.
Ниже приведена функция, которая создает точки:
function addCirclesForArray(element,index,array) {
var coordinates =
projection([element.sendLocation.longitude,element.sendLocation.latitude]);
g.append("circle")
.attr("cx",coordinates[0])
.attr("cy",coordinates[1])
.attr("r",(index<array.length-1)?2:4)
.attr("r",4)
.style("fill",$colorScale(d3.round(element.profileReadings[0].psal)))
.attr("class","circle")
g.selectAll("circle")
.on("click",circleClicked)
}
И вот мой метод для обработки json-данных для всплывающих окон jQuery:
function circleClicked(data, i) {
console.log(data) // undefined
console.log(i); // index #
$.getJSON("data/oc-readings3.json", function(data){
$.each(data, function(key, value){
//populate jQuery dialog
$('#floatID').text("Float ID: "+value.platformNumber);
$('#latitude').text("Latitude: "+value.sendLocation.latitude);
$('#longitude').text("Longitude: "+value.sendLocation.longitude);
// jQuery UI dialog and tabs
$( "#tabs" ).tabs();
$( "#dialog" ).dialog({ width: 400 })
});
});
}
Я, вероятно, пропустил что-то простое с циклом в методе getJSON, или, возможно, это связано с неопределенностью данных. Если у вас есть какие-либо советы, пожалуйста, дайте мне знать. Благодарю.
UPDATE/Solution Я понял, что мне не нужно использовать $.getJSON, так как я уже получал json-данные в методе addCirclesForArray. Я мог бы просто использовать индекс из переданного параметра массива.
Я также избавился от метода circleClicked и добавил новую логику к методу addCirclesForArray.
g.selectAll("circle")
.on("mouseover", increaseSize)
.on("mouseout", decreaseSize)
.on("click", function(d,i) {
//console.log(array[i]);
//jQuery popup
$( "#tabs" ).tabs();
$( "#dialog" ).dialog({
width: 418,
resizable: false
});
//populate tabs
$('#floatID').text("Float ID: "+array[i].platformNumber);
// etc.
Когда вы привязываете обработчик (щелчок мыши, указатель мыши и т.д.), Используя d3 selection.on (тип, обратный вызов), ваша функция обратного вызова вызывается со своим контекстом ("это"), привязанным к узлу DOM, который был нажат, а данные элемента как его первый параметр. Чтобы это сработало, вам нужно сначала привязать данные к DOM-узлам DOM/SVG, созданным D3.
Я рекомендую использовать декларативную привязку данных вместо циклирования элементов данных. Создатель D3 Майк Босток предлагает общий обзор декларативного связывания в d3 ("присоединяется"), а также подробное техническое объяснение.
Что касается диалога, основной идеей является определение только одного диалога/всплывающей подсказки/всплывающей подсказки, которая сначала скрыта и повторно используется для каждого щелкнутого узла. Из функции обратного вызова вы можете заменить поля заполнителя в своем диалоговом окне фактическими значениями вашего объекта данных.
Возможно, ваш пример может быть изменен, чтобы выглядеть так:
var containerElement = $('#container'),
svg = d3.select(containerElement).append('svg')
/* .attr('width', ...).attr('height',...)*/;
// jQuery UI dialog and tabs
$( "#tabs" ).tabs();
$( "#dialog" ).dialog({ width: 400 });
$.getJSON("data/oc-readings3.json", addCirclesForArray);
/** called only once */
function addCirclesForArray(data) {
var coordinates = [];
$.each(data, function(key, value){
coordinates.push(projection([value.sendLocation.longitude, value.sendLocation.latitude]));
});
// data join / declarative binding
// caution: binding requires an array of array(s)!
var groups = svg.selectAll('g').data([data]);
// exit
groups.exit().remove();
// enter
groups.enter().append("svg:circle");
// enter + update
groups.attr("cx",coordinates[0])
.attr("cy",coordinates[1])
.attr("r", function(d,index) {
return (index<array.length-1)? 2: 4;
})
//.attr("r", 4) // duplicate assignment of r
.style("fill", function(d) {
return $colorScale(d3.round(d.profileReadings[0].psal));
})
.attr("class","circle");
groups.selectAll("circle")
.on("click", circleClicked); // :TODO: bind circleClicked to your preferred context
}
/**
* @param {arrayElement} data
* @this {svg:circle}
*/
function circleClicked(data) {
var dialog = $('dialogPlaceholder');
$('#floatID', dialog).text("Float ID: " + data.platformNumber);
$('#latitude', dialog).text("Latitude: " + data.sendLocation.latitude);
$('#longitude', dialog).text("Longitude: " + data.sendLocation.longitude);
}