2013-05-30 16 views
6

l'aggiornamento ad esempio grafico a torta sul sito bl.ocks non aggiorna gli elementi 'a posto':È possibile creare grafici a torta con coerenza dell'oggetto?

http://bl.ocks.org/j0hnsmith/5591116

function change() { 
    clearTimeout(timeout); 
    path = path.data(pie(dataset[this.value])); // update the data 
    // set the start and end angles to Math.PI * 2 so we can transition 
    // anticlockwise to the actual values later 
    path.enter().append("path") 
     .attr("fill", function (d, i) { 
     return color(i); 
     }) 
     .attr("d", arc(enterAntiClockwise)) 
     .each(function (d) { 
     this._current = { 
      data: d.data, 
      value: d.value, 
      startAngle: enterAntiClockwise.startAngle, 
      endAngle: enterAntiClockwise.endAngle 
     }; 
     }); // store the initial values 

    path.exit() 
     .transition() 
     .duration(750) 
     .attrTween('d', arcTweenOut) 
     .remove() // now remove the exiting arcs 

    path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs 
} 

Invece, appena considera il nuovo array di valore come nuovi dati e ridimensiona il grafico di conseguenza.

Ho creato un violino che dimostra la questione in modo molto semplice:

http://jsfiddle.net/u9GBq/23/

Se si preme 'add', è aggiungere un int casuale alla matrice: questo funziona come previsto.

Se si preme "Rimuovi", l'unico elemento che viene eliminato è sempre l'ultimo elemento che ha inserito la torta. In breve, si comporta come uno stack LIFO. Il comportamento atteso prevede invece la transizione dell'arco della torta pertinente.

È possibile applicare la consistenza dell'oggetto alle torte? Ho anche provato ad aggiungere una funzione chiave (non dimostrata sul violino) ma che si rompe appena (stranamente funziona bene con i miei grafici sovrapposti).

Grazie.

+0

Potete fornire un esempio grafico di quello che vuoi dire - quello che ci si aspetta di vedere prima e dopo l'aggiunta di un nuovo elemento? Non è chiaro per me - una torta rappresenta essenzialmente il 100% di un set di dati. Quando aggiungi un nuovo elemento a un grafico a torta, tutti gli altri elementi devono ridursi proporzionalmente e anche il contrario è vero. – mccannf

+0

Ciao mccannf, grazie per il tuo commento. Se guardi il secondo jsfiddle collegato nel mio post originale, puoi vedere che quando premi 'remove' rimuovi uno specifico elemento casuale dal set. Mi aspetto che questo particolare arco passi. Al contrario, ricolora tutti gli archi con nuovi colori e ne elimina l'ultimo inserito, non riflettendo più il set di dati sottostante. Per questo motivo, sembra che d3 non stia preservando gli indici. –

+0

Ok, capito. Sarebbe utile qualcosa di simile a questo esempio: http://bl.ocks.org/mbostock/3888852. Qui mbostock ha assegnato un dominio di colori alle intestazioni dei dati e una legenda associata. – mccannf

risposta

11

La soluzione più semplice a questo problema è quello di valori mancanti impostati a zero, anziché rimuoverle completamente, come nel Part III della serie Pie Chart Update di esempi. Quindi ricevi object constancy gratuitamente: hai lo stesso numero di elementi, nello stesso ordine, tra gli aggiornamenti.

In alternativa, se si desidera che un dato aderire come in Part IV, bisogna dire D3, dove gli archi entranti dovrebbero entrare da, e dove gli archi in uscita dovrebbero uscita. Una strategia ragionevole consiste nel trovare l'arco adiacente più vicino dai dati opposti: per un dato arco entrante, trova l'arco adiacente più vicino nei vecchi dati (pre-transizione); allo stesso modo per un determinato arco in uscita, trova l'arco adiacente più vicino nei nuovi dati (post-transizione).

Per continuare l'esempio, supponiamo di mostrare vendite di mele in regioni diverse e di passare a mostrare arance. È possibile utilizzare la seguente funzione chiave per mantenere la costanza dell'oggetto:

function key(d) { 
    return d.data.region; 
} 

(Questo presuppone che si sta utilizzando d3.layout.pie, che avvolge i dati originali e lo espone come d.data.)

Ora dici quando si transizione alle arance, si hanno i seguenti dati vecchi e nuovi dati:

var data0 = path.data(), // retrieve the old data 
    data1 = pie(region.values); // compute the new data 

Per ogni arco immettendo all'indice i (dove d è data1[i]), è possibile passare in sequenza precedente dati in data1, e vedere se è possibile trovare una corrispondenza in data0:

var m = data0.length; 
while (--i >= 0) { 
    var k = key(data1[i]); 
    for (var j = 0; j < m; ++j) { 
    if (key(data0[j]) === k) return data0[j]; // a match! 
    } 
} 

Se si trova una corrispondenza, i tuoi archi entranti possono partire da dell'arco corrispondente fine di un ngle. Se non trovi una corrispondenza precedente, puoi cercare un arco di corrispondenza successivo. Se non ci sono corrispondenze, non c'è sovrapposizione tra i due set di dati, quindi è possibile inserire gli archi dall'angolo 0 ° o eseguire un crossfade. Puoi anche applicare questa tecnica per uscire dagli archi.

Mettere tutto insieme, ecco Part V:

pie chart update v

+0

Parte V, solo per me :) Sì !!!! Grazie mille Mike !!!!!!! –

0

Ok, ho trovato la soluzione. Il trucco è stato quello di passare la chiave in questo modo:

path = path.data(pie(dataset), function (d) {return d.data}); // this is good 

al contrario di non passarla, o passando nel modo sbagliato:

path = path.data(pie(dataset, function (d) {return d.data})); // this is bad 

Ed ecco un violino aggiornato con una transizione di lavoro sulla arco giusto! :)

http://jsfiddle.net/StephanTual/PA7WD/1/

+2

Non pensare che sia giusto. Se la tua funzione chiave è 'return d.data', allora tutte le tue chiavi saranno' "[object Object]" 'e accadranno cose brutte. Per favore vedi la mia risposta, e consiglio anche di leggere il [tutorial sulla costanza degli oggetti] (http://bost.ocks.org/mike/constancy/) sulle funzioni chiave. – mbostock

+0

Wow Sono stato istruito da Mbostock stesso, è un onore! Grazie Mike per la risposta dettagliata qui sotto, ti voterò. –

Problemi correlati