2016-03-10 3 views
0

Я работаю с диаграммой рассеивания в d3. Точки на графике представляют собой бумагу. При правом щелчке точки у меня есть контекстное меню, в котором есть 2 варианта: 1) добавить эту бумагу в библиотеку (тип изменения в In_library) и 2) Удалить из библиотеки (полностью удалить бумагу из данных).Функция обновления не называется должным образом d3

Я вызываю функцию refreshGraph() после каждого из этих обновлений, которое перерисовывает график с обновленными данными. Но ничего не происходит, что я предполагаю, потому что refreshGraph() не называется должным образом? Или для библиотеки типов 1-го типа не устанавливается должным образом? Когда refreshGraph вызывается после опции 1, точка должна стать синей, а при вызове для опции 2 точка должна исчезнуть с дисплея, поскольку она была удалена из alldata, которая является данными, которые используются для рисования кругов. Вот соответствующий код:

allData = []; 

var menu = [{ 
title: 'Add to Library', 
action: function addToLibrary(elem, d, i) { 

    d3.json("connection6.php?paperID="+d.ID, function(error, dataJson) { 

     for(i=0;i<allData.length;i++){ 
      if (d.type === "In_library") 
      { 
      alert("The paper: " + d.TITLE + " is already in your Library!"); 
        return; 
      } 
      } 

      d.type = "In_library"; // is this the correct way to change the type if the input has a different type?? 
      refreshGraph(); 

     }) 
     refreshGraph(); 
    } 

}, 
{ 
title: 'Remove from Library', 
action: function removeFromLibrary (elem, d, i) { 

     d3.json("connection9.php?paperID="+d.ID, function(error, dataJson) { 

      //loop through allData and if selected ID has type In_library, remove from allData 
      for(i=0;i<allData.length;i++){ 
       if (d.type == "In_library"){ 
        allData.splice(i--,1);  
      } 
      } 
      refreshGraph(); 
      }) 
    } 

} 
] 

function refreshGraph() { 

// draw dots 
var circles = svg.selectAll("circle") 
     .data(allData) 

    circles.transition() 
     .attr("cx", function(d) {return x(YearFn(d))}) 
     .attr("cy", function(d) {return y(Num_citationsFn(d))}) 

    circles.enter() 
     .append("circle") 
     .attr("class", "dot") 
     .attr("r", 3.5) 
     .attr("cx", function(d) {return x(YearFn(d))}) 
     .attr("cy", function(d) {return y(Num_citationsFn(d))}) 
     .style("fill",function(d){ 
        var colour = "black" 
        switch(d.type){ 

        case "In_library": 
         colour = "blue"; 
        break; 
        case "cited by": 
         colour = "red"; 
        break; 
        case "cites": 
         colour = "green"; 
        break; 
        case "selected": 
         colour = "magenta"; 
        break; 
        default: 
         colour = "black"; 
        } 
        return colour; 
        }) 

     .on("mouseover", mouseHandler) 
     .on("mouseout", mouseoutHandler) 
     .on("click", clickHandler) 
     .on("contextmenu", rightClickHandler); 


svg.select(".y.axis").call(yAxis); 
svg.select(".x.axis").call(xAxis); 

//don't want dots overlapping axis, so add in buffer to data domain 
x.domain([d3.min(allData, YearFn)-1, d3.max(allData, YearFn)+1]); 
y.domain([d3.min(allData, Num_citationsFn)-1, d3.max(allData, Num_citationsFn)+1]); 

    } 

Любая помощь очень ценится Я новичок в d3, поэтому спасибо заранее!

+0

Вы забыли обновить 'allData' в своей функции' addTolibrary'? – Quarter2Twelve

+0

@ Quarter2Twelve yes good point Вы имеете в виду push (d) во всеДата? Если так, что не должно быть так, как если бы точка отображалась и ее можно было щелкнуть, она означает, что она уже находится во всехData .. так что, если я нажимаю эту бумагу во всеДата, она рисует другой экземпляр этой бумаги поверх нее, вместо которой я бы хотел тип, который следует распознать как In_library, и изменить цвет существующей точки. Я попробовал это и увидел голубую точку, но понял, что это просто покрывает другую точку. –

+0

Когда вы вызываете refreshGraph, что вы делаете с кругами, которые уже построены? – James

ответ

1

Вам не нужно перепланировать все данные каждый раз, когда изменяется одна точка. Просто обновите эту точку.

function rightClickHandler() { 

    // if option 1 
    d3.select(this).style("fill", "blue"); 

    // if option 2 
    d3.select(this).remove(); 

} 

Ваша проблема возникает потому, что, скорее всего, когда вы звоните refreshGraph во второй раз (или третий) ваш не ясно, что круги, которые уже нанесены. Ваша функция refreshGraph не обновляет уже созданные точки, каждый раз воссоздавая их, и если вы не очищаете точки, которые уже есть, вы не увидите новых точек (или их отсутствия или изменения в цвет), потому что они скрыты за вашими старыми точками.

EDIT:

Если вы хотите повторно добавить данные каждый раз, вы должны сначала очистить существующие данные. В начале вашей функции refreshGraph, добавьте следующую строку:

if(!d3.selectAll("circle").empty()) d3.selectAll("circle").remove(); 

т.е. если есть круг элементов, удалить их. Предполагается, что вы создаете только элементы окружности в функции refreshGraph. Если вы создадите их в другом месте, вы, скорее всего, должны использовать селектор .dot.

+0

ah ok Я думаю, что вижу, откуда вы. Добавление данных не является проблемой, поэтому проблема заключается в том, что мне нужно изменить точку на другой тип, поскольку сначала мне нужно ее удалить, а затем перерисовать (я хочу, чтобы refreshgraph перерисовал это в цвете, который распознает тип как - поэтому я не действительно хочу использовать ваш setAttribute (это), если я могу его избежать). И то же самое с удалением из библиотеки, возможно, я удалил ее из данных, но я не удалил ее с экрана. Извините, что я говорю через свои мысли, чтобы вы могли дать мне указания на то, как я могу удалить оригинал и перерисовать ?? –

+0

Несомненно, см. Редактирование. – James

+0

хороший! действительно оцените это, просто чтобы задать вам еще один вопрос .. когда я выберем опцию «Удалить из библиотеки» и график обновления звонков, все будет удалено из экрана, когда мне нужно удалить только выбранный круг ... как бы я это сделал? в функции removeFromLibrary? Является ли моя петля правильной или даже необходимой? Сначала вы редактируете 'd3.select (this).remove(); 'имеет смысл для меня, но когда я помещаю его в функцию removeFromLibrary, он не работает. Надеюсь, вы можете мне помочь. Я очень ценю обратную связь @James –

Смежные вопросы