Sök…


Syntax

  • d3. välj (väljare)
  • d3. selectAll (selector)
  • urval . välj (väljare)
  • urval . selectAll (selector)
  • urval . filter (filter)
  • urval . slå samman (annat)

Anmärkningar

Relaterade avläsningar:

Grundläggande urval och ändringar

Om du är bekant med jQuery och Sizzle syntax, bör d3 val inte vara mycket annorlunda. d3 efterliknar W3C Selectors API för att underlätta interaktion med element.

För ett grundläggande exempel för att välja alla <p> och lägga till en ändring till var och en av dem:

d3.selectAll('p')
  .attr('class','textClass') 
  .style('color', 'white');

I ett nötskal är detta relativt detsamma som att göra i jQuery

$('p')
  .attr('class','textClass') 
  .css('color, 'white')

Generellt börjar du med ett enda val i din container div för att lägga till ett SVG-element som kommer att tilldelas en variabel (oftast kallad svg).

var svg = d3.select('#divID').append('svg');

Härifrån kan vi uppmana svg att göra våra delval av flera objekt (även om de inte ännu finns).

svg.selectAll('path')

Olika väljare

Du kan välja element med olika väljare:

  • av tagg: "div"
  • efter klass: ".class"
  • av id: "#id"
  • av attribut: "[color=blue]"
  • flera väljare (ELLER): "div1, div2, class1"
  • flera väljare (OCH): "div1 div2 class1"

Enkel val av begränsad data

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");

Placeringarnas roll i "enter" -valen

Vad är ett val?

I D3.js, när man binder data till DOM-element, är tre situationer möjliga:

  1. Antalet element och antalet datapunkter är desamma;
  2. Det finns fler element än datapunkter;
  3. Det finns fler datapunkter än element;

I den situation # 3, alla datapunkter utan motsvarande DOM-element tillhör anger valet. Således, i D3.js, anger val är val som, efter att ha kopplat element till data, innehåller alla data som inte matchar något DOM-element. Om vi använder en append funktion i en ange val kommer D3 skapa nya element bindning som data för oss.

Detta är ett Venn-diagram som förklarar de möjliga situationerna för antalet datapunkter / antal DOM-element:

ange bildbeskrivning här

Som vi kan se, den anger valet är det blå området på vänster: datapunkter utan motsvarande DOM-element.

Strukturen för Enter-valet

Vanligtvis har ett enter- val följande fyra steg:

  1. selectAll : Välj element i DOM;
  2. data : Räknar och analyserar data;
  3. enter : Jämför valet med data, skapar nya element;
  4. append : Lägg till de faktiska elementen i DOM;

Detta är ett mycket grundläggande exempel (titta på de fyra stegen i 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; });

Och detta är resultatet ( jsfiddle här ):

ange bildbeskrivning här

Lägg märke till att vi i detta fall använde selectAll("div") som den första raden i vår "enter" -valvariabel. Vi har ett dataset med 6 värden, och D3 skapade 6 div för oss.

Platshållarnas roll

Men anta att vi redan har en div i vårt dokument, något som <div>This is my chart</div> överst. I så fall när vi skriver:

body.selectAll("div")

vi väljer den befintliga div. Så vårt val av enter kommer att ha endast 5 datum utan matchande element. Till exempel, i denna jsfiddle , där det redan finns en div i HTML ("Detta är mitt diagram"), kommer detta att bli resultatet:

ange bildbeskrivning här

Vi ser inte värdet "40" längre: vår första "bar" försvann, och orsaken till detta är att vårt "enter" -val nu bara har fem element.

Vad vi måste förstå här är att i den första raden i vår enter- selectAll("div") , selectAll("div") är dessa divs bara platshållare . Vi behöver inte välja alla divs om vi lägger till divs , eller alla circle om vi lägger till circle . Vi kan välja olika saker. Och om vi inte planerar att välja en "uppdatering" eller ett "exit" -val, kan vi välja vad som helst :

var divs = body.selectAll(".foo")//this class doesn't exist, and never will!
    .data(data)
    .enter()
    .append("div");

På detta sätt väljer vi alla ".foo". Här är "foo" en klass som inte bara inte finns utan också skapas aldrig någon annanstans i koden! Men det spelar ingen roll, det här är bara en platshållare. Logiken är denna:

Om du väljer något som inte finns i ditt "enter" -val kommer ditt "enter" -val alltid att innehålla alla dina data.

Nu väljer du .foo , vårt "enter" -val har 6 element, även om vi redan har en div i dokumentet:

ange bildbeskrivning här

Och här är motsvarande jsfiddle .

Val av null

Det överlägset bästa sättet att garantera att du väljer ingenting är att välja null . Inte bara det, utan detta alternativ är mycket snabbare än något annat.

Således, för ett val av val, gör du bara:

selection.selectAll(null)
    .data(data)
    .enter()
    .append(element);

Här är en demonstrationsfiol: https://jsfiddle.net/gerardofurtado/th6s160p/

Slutsats

När du arbetar med "enter" -val måste du vara extra försiktig så att du inte väljer något som redan finns. Du kan använda allt i ditt selectAll , även saker som inte existerar och aldrig kommer att existera (om du inte planerar att ha en "uppdatering" eller ett "exit" -val).

Koden i exemplen är baserad på den här koden av Mike Bostock: https://bl.ocks.org/mbostock/7322386

Använda "detta" med en pilfunktion

De flesta funktioner i D3.js accepterar en anonym funktion som ett argument. De vanliga exemplen är .attr , .style , .text , .on och .data , men listan är mycket större än så.

I sådana fall utvärderas den anonyma funktionen för varje valt element i ordning som skickas:

  1. Det aktuella datumet ( d )
  2. Aktuellt index ( i )
  3. Den nuvarande gruppen ( nodes )
  4. this som det aktuella DOM-elementet.

Datumet, indexet och den aktuella gruppen ges som argument, det berömda första, andra och tredje argumentet i D3.js (vars parametrar traditionellt heter d , i och p i D3 v3.x). För att använda this behöver man dock inte använda något argument:

.on("mouseover", function(){
    d3.select(this);
});

Ovanstående kod kommer att välja this när musen är över elementet. Kontrollera att det fungerar i den här fiolen: https://jsfiddle.net/y5fwgopx/

Pilfunktionen

Som en ny ES6-syntax har en pilfunktion en kortare syntax jämfört med funktionsuttryck. Men för en D3-programmerare som använder this ständigt finns det en fallgrop: en pilfunktion skapar inte sin egen this sammanhang. Det innebär att det i en pil funktion, this har sin ursprungliga betydelse från omslutande sammanhang.

Detta kan vara användbart under flera omständigheter, men det är ett problem för en kodare som är van vid att använda this i D3. Om du till exempel använder samma exempel i fiolen ovan fungerar detta inte:

.on("mouseover", ()=>{
    d3.select(this);
});

Om du tvivlar på det här är fiolen: https://jsfiddle.net/tfxLsv9u/

Det är inte ett stort problem: man kan helt enkelt använda ett vanligt, gammaldags funktionsuttryck när det behövs. Men vad händer om du vill skriva all din kod med hjälp av pilfunktioner? Är det möjligt att ha en kod med pil funktioner och fortfarande korrekt använda this i D3?

Det andra och det tredje argumentet tillsammans

Svaret är ja , eftersom this är samma för nodes[i] . Tipset finns faktiskt över hela D3 API när det beskriver detta:

... med this som det aktuella DOM-elementet ( nodes[i] )

Förklaringen är enkel: eftersom nodes är den aktuella gruppen av element i DOM och i är indexet för varje element, hänvisar nodes[i] till det aktuella DOM-elementet i sig. Det är, this .

Därför kan man använda:

.on("mouseover", (d, i, nodes) => {
    d3.select(nodes[i]);
});

Och här är motsvarande fiol: https://jsfiddle.net/2p2ux38s/



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow