2012-07-02 7 views
17

Ho un set di dati che sto visualizzando con d3.js. L'asse x rappresenta il tempo (in minuti). Mi piacerebbe visualizzare questo asse in un formato hh:mm e non riesco a trovare un modo per farlo in modo pulito all'interno di d3.Come si crea un formattatore di assi personalizzato per ore e minuti in d3.js?

Il mio codice asse assomiglia:

svg.append('g') 
    .attr('class', 'x axis') 
    .attr('transform', 'translate(0,' + height + ')') 
    .call(d3.svg.axis() 
    .scale(x) 
    .orient('bottom')); 

che genera etichette in minuti che assomiglia [100, 115, 130, 140], ecc

La mia soluzione attuale è quella di selezionare gli elementi text dopo che sono stati generati e sostituiscile con una funzione:

svg.selectAll('.x.axis text') 
    .text(function(d) { 
     d = d.toFixed(); 
     var hours = Math.floor(d/60); 
     var minutes = pad((d % 60), 2); 
     return hours + ":" + minutes; 
    }); 

Questo asse di uscite segni di spunta come [1:40, 1:55, 2:10], ecc.

Ma questo si sente janky ed evita l'uso di d3.format. C'è un modo migliore per fare queste etichette?

risposta

52

Se avete tempo assoluto, probabilmente si desidera convertire i x dati a JavaScript Date objects piuttosto che semplici numeri, e poi si desidera utilizzare d3.time.scale e d3.time.format. Un esempio di "hh: mm" formato per un asse sarebbe:

d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 
    .tickFormat(d3.time.format("%H:%M")); 

E in realtà, potrebbe non essere necessario specificare un formato tick a tutti; a seconda del dominio della bilancia e del numero di zecche, lo default time scale format potrebbe essere sufficiente per le tue esigenze. In alternativa, se si desidera il controllo completo, è anche possibile specificare gli intervalli di graduazione sulla scala. Ad esempio, per le zecche ogni quindici minuti, si potrebbe dire:

d3.svg.axis() 
    .scale(x) 
    .orient("bottom") 
    .ticks(d3.time.minutes, 15) 
    .tickFormat(d3.time.format("%H:%M")); 

Se avete tempo relativo, cioè durate, (e quindi avere numeri che rappresentano minuti anziché date assolute), è possibile formattare questi come date selezionando un'epoca arbitraria e convertendole al volo. In questo modo puoi lasciare i dati stessi come numeri. Per esempio:

var formatTime = d3.time.format("%H:%M"), 
    formatMinutes = function(d) { return formatTime(new Date(2012, 0, 1, 0, d)); }; 

Dal momento che verranno visualizzati solo i minuti e le ore, non importa quale epoca si sceglie. Ecco un esempio di utilizzo di questa tecnica per formattare una distribuzione delle durate:

+0

Suppongo Avrei detto, il mio caso d'uso è un istogramma (con gli oggetti che rappresentano cestinate tempo). Siccome sono abbastanza sicuro che questo ha impostato una scala ordinale, non sono stato in grado di farlo funzionare. Forse sto solo mescolando concetti incompatibili? Ecco il mio codice (asse in basso): http://pastebin.com/Wkcexcgr – matthewsteele

+3

Ho modificato la mia risposta e aggiunto un esempio che mostra come utilizzare la seconda tecnica in combinazione con un istogramma di durate. – mbostock

+2

Questo ha funzionato. Grazie per tutto il vostro aiuto! Davvero stupito di ciò che hai costruito. – matthewsteele

Problemi correlati