Questa è chiamata una funzione anonima, che è una funzione a cui non viene assegnata un'etichetta con nome. Le funzioni anonime in Javascript sono oggetti come tutto il resto ed è per questo che puoi passarli come parametri in altre funzioni javascript.
Nel caso di d3, consente di passare una funzione come secondo parametro. Come hai scoperto, questa funzione verrà chiamata con l'elemento dati corrente e l'indice dell'elemento di dati corrente. Se il secondo parametro non è una funzione, può invece utilizzare un valore.
Nel tuo esempio:
d3.selectAll("circle")
.attr("cy",function (d) { return percent_scale(d.late_percent);})
.attr("cx",function (d) { return time_scale(d.time);})
.attr("r",1);
Sia cy
e cx
vengono valori assegnati in base al valore di ritorno di una chiamata di funzione anonima, mentre r
viene assegnato un valore statico. Potremmo riscrivere questo come:
function setY(d) { return percent_scale(d.late_percent);}
function setX(d) { return time_scale(d.time); }
d3.selectAll("circle")
.attr("cy", setY)
.attr("cx", setX)
.attr("r",1);
Qui ho sostituito la funzione di chiamate anonime con le definizioni più funzionali standard e specificate il nome della funzione da chiamare nella chiamata d3
. Funziona esattamente come prima. Nota anche che in questo caso non c'è nulla di magico in d
.
function setY(foo) { return percent_scale(foo.late_percent);}
function setX(foo) { return time_scale(foo.time); }
d3.selectAll("circle")
.attr("cy", setY)
.attr("cx", setX)
.attr("r",1);
Questo codice farà anche la stessa cosa. Nota che ho rinominato il parametro da d
a foo
, ma questo cambia semplicemente il modo in cui accedi al parametro all'interno della funzione. Non ha effetto al di fuori della chiamata di funzione. Generalmente nella documentazione e nelle esercitazioni d3
, vedrai d
utilizzato per l'elemento dati corrente e i
utilizzato per l'indice dell'elemento di dati corrente. L'indice è passato come secondo elemento di chiamate di funzione in questo modo:
function setY(d, i) { return percent_scale(d.late_percent);}
function setX(d, i) { return time_scale(d.time); }
d3.selectAll("circle")
.attr("cy", setY)
.attr("cx", setX)
.attr("r",1);
Ora specificatamente nel caso d3
:
// Select all of the 'circle' elements (that is <circle>) elements
// in the HTML document and put the associated data into an array
d3.selectAll("circle")
// For each circle element, set the Y position to be the result
// of calling percent_scale on the data element late_percent
.attr("cy",function (d) { return percent_scale(d.late_percent);})
// For each circle element, set the X position to be the result
// of calling time_scale on the data element time
.attr("cx",function (d) { return time_scale(d.time);})
// For each circle element, set the radius to be 1
.attr("r",1);
Questo è un costrutto molto comune in d3
. Il primo passo è sempre quello di fare una selezione per definire quale serie di elementi si desidera modificare (questo è il .selectAll in questo caso). Successivamente, è possibile concatenare chiamate aggiuntive (in questo caso le chiamate .attr) che eseguono effettivamente le modifiche desiderate agli elementi.
Questo crea un metodo molto efficace per lavorare con documenti basati sui dati (come grafici, grafici, ecc.) Senza dover tracciare manualmente gli elementi di dati o creare molti loop. In effetti, di solito puoi dire che stai usando d3
in modo errato se hai del loop nel tuo codice che riguarda gli elementi di modifica.
Se non si ha molta esperienza con javascript, le esercitazioni su https://www.dashingd3js.com/ potrebbero essere utili per iniziare con d3
.
Grazie per la spiegazione dettagliata! – user3562812