D3.js и jQuery - несколько точек на карте и события кликов

0

Я новичок в 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.
  • 0
    Где вы связываете данные с кругами?
  • 0
    Спасибо за ваш ответ. Я только привязываю данные к html для диалога jQuery, а не к кругу. Может быть, это моя проблема?
Показать ещё 2 комментария
Теги:
d3.js

1 ответ

0

Когда вы привязываете обработчик (щелчок мыши, указатель мыши и т.д.), Используя 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);
}
  • 0
    Спасибо за ваш код переписать, объяснения и ссылки. Карта теперь не заполнена точками, и всплывающие окна не работают правильно, поэтому я буду работать над полным пакетом, как предложил FernOfTheAndes, поскольку вы, ребята, видели только часть моего кода.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню