2015-12-04 10 views
22

Stworzyłem tabelę donut d3. Oto mój kod:D3: Jak odświeżyć wykres z nowymi danymi?

var width = 480; 
var height = 480; 
var radius = Math.min(width, height)/2; 
var doughnutWidth = 30; 

var color = d3.scale.category10(); 

var arc = d3.svg.arc() 
.outerRadius(radius - 10) 
.innerRadius(radius - 70); 

var pie = d3.layout.pie() 
.sort(null) 
.value(function(d) { return d[1]; }); 

var dataset = settings.dataset; 
console.log(dataset); 

var svg = d3.select("body") 
.append("svg") 
.attr("width", width) 
.attr("height", height) 
.append("g") 
.attr("transform", "translate(" + width/2 + "," + height/2 + ")"); 

var path = svg.selectAll('path') 
.data(pie(dataset)) 
.enter() 
.append('path') 
.attr('d', arc) 
.attr('fill', function(d, i) { 
    return color(d.data[0]); 
}) 

Mam prosty formularz na mojej stronie internetowej, który wyświetla rozwijane menu z kilkoma opcjami. Za każdym razem, gdy użytkownik zmienia wartość w formularzu, nowy zestaw danych jest wysyłany do mojego skryptu (settings.dataset), a pączek jest przerysowywany na stronie.

Problem polega na tym, że niektóre wartości z poprzedniego zestawu danych pozostają w DOM. W poniższym wyjściu konsoli widać, że drugi zestaw danych zawiera tylko dwa elementy. Trzeci pochodzi z poprzedniego zestawu danych. To psuje wykres, ponieważ wyświetla wartość, której nie powinno tam być.

enter image description here

Moje pytanie: w jaki sposób mogę wyczyścić stare wartości? Przeczytałem na numerach .exit() i .remove(), ale nie mogę zrozumieć tych metod.

+0

, więc kod, który wkleiłeś powyżej, zostanie wykonany za każdym razem na udate? – Cyril

+0

Tak, skrypt jest wywoływany za każdym razem, gdy użytkownik wybiera inną opcję w moim formularzu. – 24ma13wg

+1

Jeden problem, jaki widzę, to d3.select ("body") .append ("svg") oznacza, że ​​dodajesz svg za każdym razem przy aktualizacji. wykonaj d3.select ("svg"). remove(), aby upewnić się, że został usunięty przy aktualizacji. – Cyril

Odpowiedz

7

Istnieją dwa kroki do wdrożenia „przerysowanie” efekt chcesz:

pierwsze, że chcesz płótno SVG należy wyciągnąć tylko jeden raz, gdy strona jest ładowana po raz pierwszy, a następnie zaktualizować Wykres w SVG zamiast zdjac i przerysowanie SVG:

var svg = d3.select("body") 
       .selectAll("svg") 
       .data([settings.dataset]); 
// put data in an array with only one element 

// this ensures there is only one consistent svg on the page when data is updated(when the script gets executed) 
svg.enter().append("svg") 

po drugie, ze zrozumieniem enter(), exit(), istnieje wiele wspaniałych tutoriali na ten temat. W twoim przypadku, chciałbym zaproponować, aby narysować coś takiego pączka:

var path = svg.selectAll(".donut") 
      .data(settings.data) 

// bind data to elements, now you have elements belong to one of those 
// three 'states', enter, exit, or update 

// for `enter` selection, append elements 
path.enter().append("path").attr("d", arc).attr("fill", "teal") 

// for `update` selection, which means they are already binded with data 
path.transition().attrTween("d", someFunction) // apply transition here if you want some animation for data change 

// for `exit` selection, they shouldn't be on the svg canvas since there is no corresponding data, you can then remove them 
path.exit().remove() 
+0

Rozumiem: narysuj wykres raz, a następnie zaktualizuj zgodnie z wyborem użytkownika. Trochę tak: http: //bl.ocks.org/mbostock/1346410. W tej chwili ładuję tylko dane, którymi jest zainteresowany użytkownik. W tym podejściu muszę załadować wszystkie dane i przechowywać je w większej tablicy - co nie jest dużym problemem, ponieważ jest to niewielka ilość danych. Będę musiał przepisać kod dostarczający dane. Dzieki za sugestie. – 24ma13wg

+0

Przerysowywanie wykresu za każdym razem lepiej pasuje do mojego przypadku użycia, tak myślę. – 24ma13wg

+0

Jeśli chciałeś usunąć i ponownie dołączyć ścieżkę za każdym razem, przejścia() i wyjście() nie będą potrzebne, to – fengshuo

17

Utwórz jedną funkcję (re) rysuje ciasto kiedy jest utworzony i kiedy jest aktualizowana.

Nowe dane należy dodać do tortu użyciu enter() i stare dane powinny zostać usunięte za pomocą exit().remove()

Jest to tak proste, jak to:

path.enter().append("path") 
      .attr("fill", function(d, i) { return color(i); }) 
      .attr("d", arc) 
      .each(function(d) {this._current = d;}); 

    path.transition() 
      .attrTween("d", arcTween); 

    path.exit().remove() 

Pełny kod roboczych ->JSFIDDLE

+1

Co robi '.each (function (d) {this._current = d;})'? –

2
//remove and create svg 
d3.select("svg").remove(); 
var svg = d3.select("body").append("svg").attr("width","960").attr("height", "600"), 
inner = svg.append("g"); 
Powiązane problemy