Ricerca…


Sintassi

  • selection.enter ()
  • selection.exit ()
  • selection.merge ()

Aggiornamento dei dati: un esempio di base per inserire, aggiornare e uscire dalle selezioni

La creazione di un grafico che visualizza un set di dati statici è relativamente semplice. Ad esempio, se abbiamo questa matrice di oggetti come i dati:

var data = [
    {title: "A", value: 53},
    {title: "B", value: 12},
    {title: "C", value: 91},
    {title: "D", value: 24},
    {title: "E", value: 59}
];

Possiamo creare un grafico a barre in cui ogni barra rappresenta una misura, denominata "titolo", e la sua larghezza rappresenta il valore di tale misura. Poiché questo set di dati non cambia, il nostro grafico a barre ha solo una selezione "entra":

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

Qui, impostiamo la larghezza di ogni barra su 0 e, dopo la transizione, sul suo valore finale.

Questo entra nella selezione, da solo, è sufficiente per creare il nostro grafico, che puoi vedere in questo violino .

Ma cosa succede se i miei dati cambiano?

In questo caso, dobbiamo cambiare dinamicamente il nostro grafico. Il modo migliore per farlo è creare selezioni di "invio", "aggiornamento" e "uscita". Ma, prima, dobbiamo fare alcune modifiche nel codice.

Innanzitutto, sposteremo le parti che cambiano all'interno di una funzione chiamata draw() :

function draw(){
    //changing parts
};

Queste "parti che cambiano" includono:

  1. Le selezioni di invio, aggiornamento e uscita;
  2. Il dominio di ciascuna scala;
  3. La transizione dell'asse;

All'interno di tale funzione draw() , chiamiamo un'altra funzione, che crea i nostri dati. Qui, è solo una funzione che restituisce un array di 5 oggetti, scegliendo casualmente 5 lettere su 10 (ordinando alfabeticamente) e, per ognuna, un valore compreso tra 0 e 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;
};

E ora, passiamo alle nostre selezioni. Ma prima di questo, una parola di cautela: per mantenere ciò che chiamiamo costanza dell'oggetto , dobbiamo specificare una funzione chiave come secondo argomento per selection.data:

var bars = svg.selectAll(".bars")
    .data(data, function(d){ return d.title});

Senza di ciò, le nostre barre non passeranno gradualmente, e sarebbe difficile seguire i cambiamenti nell'asse (si può vedere che rimuovere il secondo argomento nel violino qui sotto).

Quindi, dopo aver impostato correttamente le nostre var bars , possiamo occuparci delle nostre selezioni. Questa è la selezione di uscita:

bars.exit()
    .transition()
    .duration(1000)
    .attr("width", 0)
    .remove();

E queste sono le selezioni di invio e di aggiornamento (in D3 v4.x, la selezione di aggiornamento viene unita alla selezione di inserimento tramite 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});

Infine, chiamiamo la funzione draw() ogni volta che si fa clic sul pulsante:

d3.select("#myButton").on("click", draw);

E questo è il violino che mostra tutte queste 3 selezioni in azione.

Unire le selezioni

Il modello di aggiornamento in D3 versione 3

Una corretta comprensione di come funzionano le selezioni "enter", "update" e "exit" è fondamentale per modificare correttamente il dataviz utilizzando D3.

Poiché D3 versione 3 (in realtà, dalla versione 2), questo snippet potrebbe impostare le transizioni per entrambe le selezioni "enter" e "update" ( demo live qui ):

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

Dando questo risultato dopo la transizione:

inserisci la descrizione dell'immagine qui

Ma cosa succede con lo stesso identico codice se usiamo la D3 versione 4? Puoi vederlo in questa demo dal vivo : niente !

Perché?

Cambiamenti nel modello di aggiornamento in D3 versione 4

Controlliamo il codice. Innanzitutto, abbiamo divs . Questa selezione associa i dati a <div> .

var divs = body.selectAll("div")
    .data(data); 

Quindi, abbiamo divs.enter() , che è una selezione che contiene tutti i dati con elementi non corrispondenti. Questa selezione contiene tutti i div nella prima volta che chiamiamo draw della funzione, e impostiamo le loro larghezze su zero.

divs.enter()
    .append("div")
    .style("width", "0px");

Poi abbiamo divs.transition() , e qui abbiamo il comportamento interessante: in D3 versione 3, divs.transition() rende tutti i <div> nella selezione "enter" che cambiano alla loro larghezza finale. Ma questo non ha senso! divs non contiene la selezione "enter" e non dovrebbe modificare alcun elemento DOM.

C'è una ragione per cui questo strano comportamento è stato introdotto in D3 versione 2 e 3 ( fonte qui ), ed è stato "corretto" in D3 versione 4. Quindi, nella demo live sopra, non succede nulla, e questo è previsto! Inoltre, se si fa clic sul pulsante, vengono visualizzate tutte le sei barre precedenti, poiché ora sono nella selezione "Aggiorna", non più nella selezione "Inserisci".

Per la transizione che agisce sulla selezione "entra", dobbiamo creare variabili separate o, un approccio più semplice, unire le selezioni :

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

Ora, abbiamo unito le selezioni "invio" e "aggiornamento". Guarda come funziona in questa demo dal vivo .



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow