d3.js
wzór aktualizacji
Szukaj…
Składnia
- selection.enter ()
- selection.exit ()
- selection.merge ()
Aktualizacja danych: podstawowy przykład wprowadzania, aktualizowania i wychodzenia z wybranych opcji
Tworzenie wykresu wyświetlającego statyczny zestaw danych jest stosunkowo proste. Na przykład, jeśli mamy tę tablicę obiektów jako dane:
var data = [
{title: "A", value: 53},
{title: "B", value: 12},
{title: "C", value: 91},
{title: "D", value: 24},
{title: "E", value: 59}
];
Możemy utworzyć wykres słupkowy, w którym każdy słupek reprezentuje miarę o nazwie „tytuł”, a jej szerokość reprezentuje wartość tej miary. Ponieważ ten zestaw danych się nie zmienia, nasz wykres słupkowy ma tylko opcję „enter”:
var bars = svg.selectAll(".bars")
.data(data);
bars.enter()
.append("rect")
.attr("class", "bars")
.attr("x", xScale(0))
.attr("y", function(d){ return yScale(d.title)})
.attr("width", 0)
.attr("height", yScale.bandwidth())
.transition()
.duration(1000)
.delay(function(d,i){ return i*200})
.attr("width", function(d){ return xScale(d.value) - margin.left});
Tutaj ustawiamy szerokość każdego słupka na 0, a po przejściu do jego końcowej wartości.
Samo wprowadzenie zaznaczenia wystarczy, aby utworzyć nasz wykres, który można zobaczyć w tym skrzypce .
Ale co jeśli moje dane się zmienią?
W takim przypadku musimy dynamicznie zmieniać nasz wykres. Najlepszym sposobem na to jest utworzenie opcji „enter”, „update” i „exit”. Ale wcześniej musimy wprowadzić pewne zmiany w kodzie.
Najpierw przeniesiemy zmieniające się części do funkcji o nazwie draw()
:
function draw(){
//changing parts
};
Te „części zamienne” obejmują:
- Wprowadź, zaktualizuj i wyjdź;
- Domena każdej skali;
- Przejście osi;
Wewnątrz tej funkcji draw()
wywołujemy inną funkcję, która tworzy nasze dane. Tutaj jest to tylko funkcja, która zwraca tablicę 5 obiektów, wybierając losowo 5 liter na 10 (sortowanie alfabetyczne) i dla każdego z nich wartość od 0 do 99:
function getData(){
var title = "ABCDEFGHIJ".split("");
var data = [];
for(var i = 0; i < 5; i++){
var index = Math.floor(Math.random()*title.length);
data.push({title: title[index],
value: Math.floor(Math.random()*100)});
title.splice(index,1);
}
data = data.sort(function(a,b){ return d3.ascending(a.title,b.title)});
return data;
};
A teraz przejdźmy do naszych wyborów. Ale wcześniej słowo ostrzeżenia: aby zachować to, co nazywamy stałością obiektu , musimy określić funkcję kluczową jako drugi argument wyboru.data:
var bars = svg.selectAll(".bars")
.data(data, function(d){ return d.title});
Bez tego nasze paski nie przejdą płynnie i trudno byłoby śledzić zmiany w osi (widać, że usunięcie drugiego argumentu w skrzypce poniżej).
Zatem po prawidłowym ustawieniu naszych var bars
możemy poradzić sobie z naszymi wyborami. Oto wybór wyjścia:
bars.exit()
.transition()
.duration(1000)
.attr("width", 0)
.remove();
Oto wybory Enter i aktualizacji (w D3 v4.x wybór aktualizacji jest scalany z wyborem Enter za pomocą merge
):
bars.enter()//this is the enter selection
.append("rect")
.attr("class", "bars")
.attr("x", xScale(0) + 1)
.attr("y", function(d){ return yScale(d.title)})
.attr("width", 0)
.attr("height", yScale.bandwidth())
.attr("fill", function(d){ return color(letters.indexOf(d.title)+1)})
.merge(bars)//and from now on, both the enter and the update selections
.transition()
.duration(1000)
.delay(1000)
.attr("y", function(d){ return yScale(d.title)})
.attr("width", function(d){ return xScale(d.value) - margin.left});
Na koniec wywołujemy funkcję draw()
każdym kliknięciu przycisku:
d3.select("#myButton").on("click", draw);
I to jest skrzypce pokazujące wszystkie te 3 selekcje w akcji.
Scalanie selekcji
Wzór aktualizacji w wersji 3 D3
Prawidłowe zrozumienie działania opcji „enter”, „update” i „exit” ma fundamentalne znaczenie dla prawidłowej zmiany dataviz przy użyciu D3.
Od wersji 3 D3 (właściwie od wersji 2) ten fragment kodu może ustawiać przejścia dla opcji „enter” i „update” ( tutaj wersja demonstracyjna na żywo ):
var divs = body.selectAll("div")
.data(data);//binding the data
divs.enter()//enter selection
.append("div")
.style("width", "0px");
divs.transition()
.duration(1000)
.style("width", function(d) { return d + "px"; })
.attr("class", "divchart")
.text(function(d) { return d; });
Podanie tego wyniku po przejściu:
Ale co stanie się z dokładnie tym samym kodem, jeśli użyjemy D3 w wersji 4? Możesz to zobaczyć w tym demo na żywo : nic !
Dlaczego?
Zmiany we wzorcu aktualizacji w wersji D3 4
Sprawdźmy kod. Po pierwsze, mamy divs
. Ten wybór wiąże dane z <div>
.
var divs = body.selectAll("div")
.data(data);
Następnie mamy divs.enter()
, która jest wyborem zawierającym wszystkie dane z niedopasowanymi elementami. Ten wybór zawiera wszystkie divy przy pierwszym wywołaniu funkcji draw
i ustawiamy ich szerokości na zero.
divs.enter()
.append("div")
.style("width", "0px");
Następnie mamy divs.transition()
, a tutaj mamy interesujące zachowanie: W wersji 3 D3 divs.transition()
powoduje zmianę wszystkich <div>
w zaznaczeniu „enter” na ich końcową szerokość. Ale to nie ma sensu! divs
nie zawiera wyboru „enter” i nie powinien modyfikować żadnego elementu DOM.
Istnieje powód, dla którego to dziwne zachowanie zostało wprowadzone w D3 w wersji 2 i 3 ( źródło tutaj ), a zostało „poprawione” w D3 w wersji 4. Tak więc, w powyższym demo na żywo nic się nie dzieje i jest to oczekiwane! Ponadto, jeśli klikniesz przycisk, pojawią się wszystkie sześć poprzednich pasków, ponieważ znajdują się one teraz w opcji „aktualizacja”, a nie w opcji „enter”.
Dla przejścia działającego nad wyborem „enter” musimy stworzyć osobne zmienne lub, łatwiejsze podejście, scalić selekcje :
divs.enter()//enter selection
.append("div")
.style("width", "0px")
.merge(divs)//from now on, enter + update selections
.transition().duration(1000).style("width", function(d) { return d + "px"; })
.attr("class", "divchart")
.text(function(d) { return d; });
Teraz połączyliśmy opcje „enter” i „update”. Zobacz, jak to działa w tym demo na żywo .