Zoeken…


Syntaxis

  • d3. selecteer (selector)
  • d3. selectAll (selector)
  • selectie . selecteer (selector)
  • selectie . selectAll (selector)
  • selectie . filter (filter)
  • selectie . samenvoegen

Opmerkingen

Gerelateerde lezingen:

Basisselectie en wijzigingen

Als u bekend bent met de syntaxis van jQuery en Sizzle, zouden d3-selecties niet veel anders moeten zijn. d3 bootst de W3C Selectors API na om interactie met elementen eenvoudiger te maken.

Voor een eenvoudig voorbeeld, om alle <p> te selecteren en een wijziging aan elk van hen toe te voegen:

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

Kort samengevat is dit relatief hetzelfde als in jQuery

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

Over het algemeen begint u met een enkele selectie aan uw containerdiv om een SVG-element toe te voegen dat wordt toegewezen aan een variabele (meestal svg genoemd).

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

Vanaf hier kunnen we een beroep doen op svg om onze subselecties van meerdere objecten te doen (zelfs als ze nog niet bestaan).

svg.selectAll('path')

Verschillende selectors

U kunt elementen met verschillende selectors selecteren:

  • op tag: "div"
  • per klasse: ".class"
  • door id: "#id"
  • by attribute: "[color=blue]"
  • meerdere selectors (OF): "div1, div2, class1"
  • meerdere selectors (AND): "div1 div2 class1"

Eenvoudige data begrensde selectie

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

De rol van tijdelijke aanduidingen bij "enter" -selecties

Wat is een enter-selectie?

Wanneer in D3.js gegevens aan DOM-elementen worden gekoppeld, zijn er drie situaties mogelijk:

  1. Het aantal elementen en het aantal datapunten zijn hetzelfde;
  2. Er zijn meer elementen dan gegevenspunten;
  3. Er zijn meer gegevenspunten dan elementen;

In situatie 3 behoren alle gegevenspunten zonder bijbehorend DOM-element tot de enter- selectie. Aldus In d3.js Voer selecties selecties die na verbindingselementen op de gegevens bevat alle gegevens die niet overeenkomen met enige DOM-element. Als we een append in een enter- selectie, maakt D3 nieuwe elementen die die gegevens voor ons binden.

Dit is een Venn-diagram dat de mogelijke situaties met betrekking tot het aantal datapunten / aantal DOM-elementen verklaart:

voer hier de afbeeldingsbeschrijving in

Zoals we kunnen zien, is de enter- selectie het blauwe gebied links: gegevenspunten zonder bijbehorende DOM-elementen.

De structuur van de enter-selectie

Doorgaans heeft een enter- selectie deze 4 stappen:

  1. selectAll : Selecteer elementen in de DOM;
  2. data : Telt en parseert de data;
  3. enter : Door de selectie met de gegevens te vergelijken, worden nieuwe elementen gemaakt;
  4. append : voeg de werkelijke elementen toe in de DOM;

Dit is een heel eenvoudig voorbeeld (bekijk de 4 stappen in de 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; });

En dit is het resultaat ( jsfiddle hier ):

voer hier de afbeeldingsbeschrijving in

Merk op dat we in dit geval selectAll("div") hebben gebruikt als de eerste regel in onze "enter" -variabele. We hebben een dataset met 6 waarden en D3 heeft 6 divs voor ons gemaakt.

De rol van tijdelijke aanduidingen

Maar stel dat we al een div in ons document hebben, zoiets als <div>This is my chart</div> bovenaan. In dat geval, wanneer we schrijven:

body.selectAll("div")

we selecteren die bestaande div. Onze invoerselectie heeft dus slechts 5 datums zonder overeenkomende elementen. In deze jsfiddle bijvoorbeeld , waar de HTML al een div bevat ("Dit is mijn grafiek"), is dit de uitkomst:

voer hier de afbeeldingsbeschrijving in

We zien de waarde "40" niet meer: onze eerste "balk" is verdwenen, en de reden daarvoor is dat onze "enter" -selectie nu slechts 5 elementen heeft.

Wat we hier moeten begrijpen, is dat in de eerste regel van onze enter-selectievariabele, selectAll("div") , deze divs slechts tijdelijke aanduidingen zijn . We hoeven niet alle divs te selecteren als we divs toevoegen, of alle circle als we circle toevoegen. We kunnen verschillende dingen selecteren. En, als we niet van plan om een "Update" of een "exit" selectie hebben, we kunnen alles selecteren:

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

Op deze manier selecteren we alle ".foo". Hier is "foo" een klasse die niet alleen niet bestaat, maar ook nooit ergens anders in de code is gemaakt! Maar het maakt niet uit, dit is slechts een tijdelijke aanduiding. De logica is deze:

Als u in uw "enter" -selectie iets selecteert dat niet bestaat, zal uw "enter" -selectie altijd al uw gegevens bevatten.

Als u nu .foo selecteert, heeft onze "enter" -selectie 6 elementen, zelfs als we al een div in het document hebben:

voer hier de afbeeldingsbeschrijving in

En hier is de bijbehorende jsfiddle .

null selecteren

Veruit de beste manier om te garanderen dat u niets selecteert, is null selecteren. Dat niet alleen, maar dit alternatief is veel sneller dan alle andere.

Voor een enter-selectie doet u dus gewoon:

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

Hier is een demo-viool: https://jsfiddle.net/gerardofurtado/th6s160p/

Conclusie

Wees bij het omgaan met "enter" -selecties extra voorzichtig om niet iets te selecteren dat al bestaat. U kunt alles in uw selectAll , zelfs dingen die niet bestaan en nooit zullen bestaan (als u niet van plan bent om een "update" of een "exit" -selectie te hebben).

De code in de voorbeelden is gebaseerd op deze code door Mike Bostock: https://bl.ocks.org/mbostock/7322386

Gebruik "this" met een pijlfunctie

De meeste functies in D3.js accepteren een anonieme functie als argument. De meest voorkomende voorbeelden zijn .attr , .style , .text , .on en .data , maar de lijst is veel groter dan dat.

In dergelijke gevallen wordt de anonieme functie geëvalueerd voor elk geselecteerd element, in volgorde, dat het wordt doorgegeven:

  1. Het huidige gegeven ( d )
  2. De huidige index ( i )
  3. De huidige groep ( nodes )
  4. this als het huidige DOM-element.

Het gegeven, de index en de huidige groep worden doorgegeven als argumenten, het beroemde eerste, tweede en derde argument in D3.js (waarvan de parameters traditioneel d , i en p in D3 v3.x). Om this , hoeft u echter geen argument te gebruiken:

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

De bovenstaande code zal this selecteren wanneer de muis zich boven het element bevindt. Controleer of het werkt in deze viool: https://jsfiddle.net/y5fwgopx/

De pijl functie

Als een nieuwe ES6-syntaxis heeft een pijlfunctie een kortere syntaxis in vergelijking met functie-expressie. Voor een D3-programmeur die this constant gebruikt, is er echter een valkuil: een pijlfunctie maakt this context niet eigen. Dat betekent dat in een pijlfunctie, this heeft zijn oorspronkelijke betekenis van de omsluitende context.

Dit kan in verschillende omstandigheden nuttig zijn, maar het is een probleem voor een codeur die gewend is this in D3 te gebruiken. Als u bijvoorbeeld hetzelfde voorbeeld in de bovenstaande viool gebruikt, werkt dit niet:

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

Als je eraan twijfelt, is hier de viool: https://jsfiddle.net/tfxLsv9u/

Nou, dat is geen groot probleem: je kunt gewoon een gewone, ouderwetse functie-uitdrukking gebruiken als dat nodig is. Maar wat als u al uw code wilt schrijven met behulp van pijlfuncties? Is het mogelijk om een code met pijl functies hebben en nog steeds goed te gebruiken this in D3?

Het tweede en derde argument gecombineerd

Het antwoord is ja , omdat this hetzelfde is als nodes[i] . De hint is eigenlijk overal in de D3 API aanwezig, wanneer deze dit beschrijft:

... met this als het huidige DOM-element ( nodes[i] )

De verklaring is eenvoudig: aangezien nodes de huidige groep elementen in de DOM is en i de index van elk element is, verwijzen nodes[i] naar het huidige DOM-element zelf. Dat is this .

Daarom kan men gebruiken:

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

En hier is de bijbehorende viool: https://jsfiddle.net/2p2ux38s/



Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow