2012-03-27 13 views
31

Ho difficoltà a comprendere gli eventi D3 e le funzioni di invio. Ho un esempio di grafico sul quale ho lavorato: "Vertical Bar Charts With Legends".Come aggiungere e utilizzare correttamente gli eventi D3?

Disegnare i grafici e le leggende è stato abbastanza facile, ma vorrei aggiungere la possibilità di evidenziare ogni barra mentre passo con il mouse sulla sua legenda di testo correlata, che si trova a destra del grafico.

Ho letto tutta la documentazione dell'evento e ho anche guardato un certo numero di esempi, molti dei quali sono piuttosto complicati, ma mi sembra che manchi qualcosa. Qualcuno saprebbe come realizzare al meglio la funzionalità di mouseover della legenda del testo che invia eventi per cambiare automaticamente i colori delle barre verticali corrispondenti?

risposta

60

Questa domanda è simile a one you posted nel gruppo Google d3-js. Senza duplicare ciò che ho scritto lì, vorrei ribadire che probabilmente non vuoi d3.dispatch; che è inteso per astrazioni di eventi personalizzati (come pennelli e comportamenti). Sarà più semplice utilizzare eventi nativi.

Se volete che il vostro leggenda per cambiare il colore della barra corrispondente al passaggio del mouse, quindi scomposizione del problema in fasi:

  1. Rileva passaggio del mouse sulla leggenda.
  2. Selezionare la barra corrispondente.
  3. Cambia il colore di riempimento della barra.

Innanzitutto, utilizzare selection.on per ascoltare gli eventi "mouseover" sugli elementi della legenda. La funzione listener verrà richiamata quando il mouse passa sopra un elemento legend e verrà richiamata con due argomenti: i dati (d) e l'indice (i). È possibile utilizzare queste informazioni per selezionare la barra corrispondente tramite d3.select. Infine, utilizzare selection.style per modificare lo stile "riempimento" con il nuovo colore.

Se non si è certi di come selezionare la barra corrispondente sul mouseover della legenda, esistono in genere diverse opzioni. La cosa più semplice è selezionare per indice, assumendo che il numero di elementi di legenda e il numero di elementi rettali siano gli stessi e che siano nello stesso ordine. In tal caso, se una variabile locale rect contiene gli elementi rect, si potrebbe dire:

function mouseover(d, i) { 
    d3.select(rect[0][i]).style("fill", "red"); 
} 

Se non si vuole fare affidamento su indice, un'altra opzione è quella di eseguire la scansione per la barra corrispondente sulla base di dati identici. Questo utilizza selection.filter:

function mouseover(d, i) { 
    rect.filter(function(p) { return d === p; }).style("fill", "red"); 
} 

Un'altra opzione è quella di dare ad ogni Rect un ID univoco, e quindi selezionare da id. Ad esempio, su di inizializzazione, si potrebbe dire:

rect.attr("id", function(d, i) { return "rect-" + i; }); 

Quindi, è possibile selezionare il rettangolo da id al passaggio del mouse:

function mouseover(d, i) { 
    d3.select("#rect-" + i).style("fill", "red"); 
} 

L'esempio di cui sopra è artificiosa da quando ho usato l'indice per generare l'ID attributo (nel qual caso, è più semplice e veloce usare la prima tecnica di selezione per indice). Un esempio più realistico sarebbe se i tuoi dati avessero una proprietà name; potresti quindi utilizzare d.name per generare l'attributo id e anche selezionare per id. Puoi anche selezionare altri attributi o classi, se non vuoi generare un ID univoco.

+0

Ciao Mike, grazie per tutto il vostro aiuto su questa roba. D3 è una grande tecnologia e mi sto godendo il mio tempo per impararlo. - Frank –

+0

FWIW questo esempio potrebbe essere implementato semplicemente aggiungendo una regola: hover CSS agli elementi SVG in questione. –

+1

@HerbCaudill A: la regola del passaggio del mouse è troppo limitante in questo caso: in questo esempio viene illustrato come modificare elementi diversi da quello al passaggio del mouse (ad esempio, dalla legenda alla barra). A: la regola del passaggio del mouse funziona solo se gli elementi che desideri modificare sono gli stessi al passaggio del mouse (ad esempio, la legenda). Vedi la mia altra risposta su [selezionare e modificare gli elementi correlati] (http://stackoverflow.com/questions/11206015/clicking-a-node-in-d3-from-a-button-outside-the-svg/11211391). – mbostock

6

La risposta di Mike è ottima.

ho usato è venuto su con questo per la selezione di una cella in una griglia stavo disegnando:

.on('click', (d, i) -> 
     console.log("X:" + d.x, "Y:" + d.y) #displays the cell x y location 
     d3.select(this).style("fill", "red"); 

Così, quando io sono l'inserimento dei dati nel Ho aggiunto il listener di eventi e l'utilizzo di d3.select (questo) .

vedere il codice nel contesto di seguito:

vis.selectAll("rect") 
    .data(singleArray) 
    .enter().append("svg:rect") 
    .attr("stroke", "none") 
    .attr("fill", (d) -> 
     if d.lifeForm 
     return "green" 
     else 
     return "white") 
    .attr("x", (d) -> xs(d.x)) 
    .attr("y", (d) -> ys(d.y)) 
    .attr("width", cellWidth) 
    .attr("height", cellHeight) 
    .on('click', (d, i) -> 
     console.log("X:" + d.x, "Y:" + d.y) 
     d3.select(this).style("fill", "red"); 
     return 
    ) 
Problemi correlati