d3.js
Wybory
Szukaj…
Składnia
- d3. wybierz (selektor)
- d3. selectAll (selektor)
- wybór . wybierz (selektor)
- wybór . selectAll (selektor)
- wybór . filtr (filtr)
- wybór . scal (inne)
Uwagi
Powiązane odczyty:
Podstawowy wybór i modyfikacje
Jeśli znasz jQuery i składnię Sizzle, wybory d3 nie powinny się znacznie różnić. d3 naśladuje interfejs API Selektorów W3C, aby ułatwić interakcję z elementami.
W podstawowym przykładzie wybierz wszystkie <p>
i dodaj zmianę do każdego z nich:
d3.selectAll('p')
.attr('class','textClass')
.style('color', 'white');
W skrócie jest to względnie to samo, co w jQuery
$('p')
.attr('class','textClass')
.css('color, 'white')
Zasadniczo zaczniesz od pojedynczego wyboru do div kontenera, aby dodać element SVG, który zostanie przypisany do zmiennej (najczęściej nazywanej svg).
var svg = d3.select('#divID').append('svg');
Stąd możemy wywołać svg
aby dokonać selekcji podrzędnej wielu obiektów (nawet jeśli jeszcze nie istnieją).
svg.selectAll('path')
Różne selektory
Możesz wybierać elementy za pomocą różnych selektorów:
- według tagu:
"div"
- według klasy:
".class"
- według identyfikatora:
"#id"
- według atrybutu:
"[color=blue]"
- wiele selektorów (OR):
"div1, div2, class1"
- wiele selektorów (AND):
"div1 div2 class1"
Prosty wybór ograniczony danymi
var myData = [
{ name: "test1", value: "ok" },
{ name: "test2", value: "nok" }
]
// We have to select elements (here div.samples)
// and assign data. The second parameter of data() is really important,
// it will determine the "key" to identify part of data (datum) attached to an
// element.
var mySelection = d3.select(document.body).selectAll("div.samples") // <- a selection
.data(myData, function(d){ return d.name; }); // <- data binding
// The "update" state is when a datum of data array has already
// an existing element associated.
mySelection.attr("class", "samples update")
// A datum is in the "enter" state when it's not assigned
// to an existing element (based on the key param of data())
// i.e. new elements in data array with a new key (here "name")
mySelection.enter().append("div")
.attr("class", "samples enter")
.text(function(d){ return d.name; });
// The "exit" state is when the bounded datum of an element
// is not in the data array
// i.e. removal of a row (or modifying "name" attribute)
// if we change "test1" to "test3", "test1" bounded
// element will figure in exit() selection
// "test3" bounded element will be created in the enter() selection
mySelection.exit().attr("class", "samples remove");
Rola symboli zastępczych w selekcjach „enter”
Co to jest wybór wejścia?
W D3.js, gdy ktoś wiąże dane z elementami DOM, możliwe są trzy sytuacje:
- Liczba elementów i liczba punktów danych są takie same;
- Jest więcej elementów niż punktów danych;
- Jest więcej punktów danych niż elementów;
W sytuacji, # 3, wszystkie punkty danych bez odpowiedniego elementu DOM należą do wprowadzić wybór. Zatem w D3.js wprowadzane selekcje to selekcje, które po połączeniu elementów z danymi zawierają wszystkie dane, które nie pasują do żadnego elementu DOM. Jeśli użyjemy funkcji append
w zaznaczeniu Enter , D3 utworzy nowe elementy wiążące te dane za nas.
Oto diagram Venna wyjaśniający możliwe sytuacje dotyczące liczby punktów danych / liczby elementów DOM:
Jak widzimy, enter wybór jest niebieski obszar po lewej stronie: punkty danych bez odpowiednich elementów DOM.
Struktura wprowadzania wyboru
Zazwyczaj wybór Enter składa się z 4 następujących kroków:
-
selectAll
: Wybierz elementy w DOM; -
data
: Zlicza i analizuje dane; -
enter
: Porównując zaznaczenie z danymi, tworzy nowe elementy; -
append
: Dołącz rzeczywiste elementy w DOM;
To jest bardzo prosty przykład (spójrz na 4 kroki w var divs
):
var data = [40, 80, 150, 160, 230, 260];
var body = d3.select("body");
var divs = body.selectAll("div")
.data(data)
.enter()
.append("div");
divs.style("width", function(d) { return d + "px"; })
.attr("class", "divchart")
.text(function(d) { return d; });
I to jest wynik ( tutaj jsfiddle ):
Zauważ, że w tym przypadku użyliśmy selectAll("div")
jako pierwszego wiersza w naszej zmiennej wyboru „enter”. Mamy zestaw danych z 6 wartościami, a D3 stworzył dla nas 6 elementów div.
Rola symboli zastępczych
Załóżmy jednak, że w naszym dokumencie znajduje się już div, coś w rodzaju <div>This is my chart</div>
na górze. W takim przypadku, kiedy piszemy:
body.selectAll("div")
wybieramy istniejący div. Zatem nasz wybór enter będzie miał tylko 5 punktów odniesienia bez pasujących elementów. Na przykład w tym pliku jsfiddle , gdzie w kodzie HTML jest już div („To jest mój wykres”), będzie to wynik:
Nie widzimy już wartości „40”: nasz pierwszy „pasek” zniknął, a powodem tego jest to, że nasz wybór „enter” ma teraz tylko 5 elementów.
Musimy tu zrozumieć, że w pierwszym wierszu naszej zmiennej wyboru enter, selectAll("div")
, te div są tylko symbolami zastępczymi . Nie musimy wybierać wszystkich elementów divs
jeśli dodajemy elementy divs
, ani całego circle
jeśli dodajemy circle
. Możemy wybierać różne rzeczy. A jeśli nie planujemy mieć opcji „aktualizacja” lub „wyjście”, możemy wybrać wszystko :
var divs = body.selectAll(".foo")//this class doesn't exist, and never will!
.data(data)
.enter()
.append("div");
W ten sposób wybieramy wszystkie pliki „.foo”. Tutaj „foo” to klasa, która nie tylko nie istnieje, ale nigdy nie została stworzona nigdzie indziej w kodzie! Ale to nie ma znaczenia, to tylko symbol zastępczy. Logika jest następująca:
Jeśli w wyborze „enter” wybierzesz coś, co nie istnieje, wybór „enter” zawsze będzie zawierał wszystkie dane.
Teraz, wybierając .foo
, nasz wybór „enter” ma 6 elementów, nawet jeśli mamy już div w dokumencie:
A oto odpowiedni jsfiddle .
Wybranie null
Zdecydowanie najlepszym sposobem na zagwarantowanie, że nic nie wybierasz, jest wybranie null
. Nie tylko to, ale ta alternatywa jest znacznie szybsza niż jakakolwiek inna.
Tak więc, aby wprowadzić wybór, po prostu wykonaj:
selection.selectAll(null)
.data(data)
.enter()
.append(element);
Oto skrzypce demonstracyjne: https://jsfiddle.net/gerardofurtado/th6s160p/
Wniosek
Podczas wybierania opcji „enter” należy zachować szczególną ostrożność, aby nie wybrać czegoś, co już istnieje. Możesz użyć wszystkiego w swoim selectAll
, nawet rzeczy, które nie istnieją i nigdy nie będą istnieć (jeśli nie planujesz mieć opcji „aktualizacja” lub „wyjście”).
Kod w przykładach jest oparty na tym kodzie autorstwa Mike'a Bostocka: https://bl.ocks.org/mbostock/7322386
Używanie „tego” z funkcją strzałki
Większość funkcji w D3.js akceptuje funkcję anonimową jako argument. Wspólne przykłady .attr
, .style
, .text
, .on
i .data
, ale lista jest o wiele większe niż to.
W takich przypadkach anonimowa funkcja jest oceniana dla każdego wybranego elementu, po kolei:
- Aktualny punkt odniesienia (
d
) - Aktualny indeks (
i
) - Bieżąca grupa (
nodes
) -
this
jako bieżący element DOM.
Punkt odniesienia, indeks i bieżąca grupa są przekazywane jako argumenty, słynny pierwszy, drugi i trzeci argument w D3.js (którego parametry tradycyjnie nazywane są d
, i
p
w D3 v3.x). Aby jednak this
użyć, nie trzeba używać żadnego argumentu:
.on("mouseover", function(){
d3.select(this);
});
Powyższy kod wybierze this
gdy wskaźnik myszy znajdzie się nad elementem. Sprawdź, czy działa w tym skrzypcach: https://jsfiddle.net/y5fwgopx/
Funkcja strzałki
Jako nowa składnia ES6, funkcja strzałki ma krótszą składnię w porównaniu do wyrażenia funkcji. Jednak dla programisty D3, kto używa this
stale, istnieje pułapka: funkcja strzałka nie tworzy własnego this
kontekst. Oznacza to, że w zależności strzałki, this
ma swoje pierwotne znaczenie z kontekstu otaczającego.
Może to być przydatne w kilku okolicznościach, ale jest to problem dla kodera przyzwyczajonego do używania this
w D3. Na przykład przy użyciu tego samego przykładu w skrzypcach powyżej to nie zadziała:
.on("mouseover", ()=>{
d3.select(this);
});
Jeśli masz co do tego wątpliwości, oto skrzypce: https://jsfiddle.net/tfxLsv9u/
Cóż, to nie jest duży problem: w razie potrzeby można po prostu użyć zwykłego, staroświeckiego wyrażenia funkcyjnego. Ale co, jeśli chcesz napisać cały kod za pomocą funkcji strzałek? Czy można mieć kod z funkcjami strzałek i nadal poprawnie używać this
w D3?
Drugi i trzeci argument łącznie
Odpowiedź brzmi tak , ponieważ this
samo dotyczy nodes[i]
. Wskazówka jest obecna w całym interfejsie API D3, gdy opisuje to:
... z
this
jako bieżącym elementem DOM (nodes[i]
)
Wyjaśnienie jest proste: ponieważ nodes
są bieżącą grupą elementów w DOM, a i
jest indeksem każdego elementu, nodes[i]
odnoszą się do samego bieżącego elementu DOM. To znaczy this
.
Dlatego można użyć:
.on("mouseover", (d, i, nodes) => {
d3.select(nodes[i]);
});
A oto odpowiednie skrzypce: https://jsfiddle.net/2p2ux38s/