2016-07-03 67 views
10

Desidero utilizzare un grafico lineare per visualizzare i miei punti dati. Chartjs sembra animare il grafico per impostazione predefinita, ma non anima i valori sull'asse x. L'asse x si sposta solo in passaggi discreti.Grafico animate asse x

C'è un modo per abilitare anche l'animazione sull'asse?

Grazie!

+0

non è chiaro se si stava chiedendo circa animare i dati del grafico nella dimensione X come CTG ha fatto seguito, o se si intende animare le etichette sulla X- asce (che è quello che ho preso la tua domanda per dire, ed è quello che stavo cercando quando ho creato la taglia), che nessuna risposta qui indirizzo. Potresti chiarire? – Aerovistae

risposta

4

Per quanto ne so, ChartJS non supporta l'animazione asse x out-of-the-box. Quindi dovrai hackerarlo. Ci sono diversi modi per farlo, ma i seguenti metodi sembrano funzionare.

Se si desidera animare i dati del X-Axis

Quando un grafico viene aggiornato, i seguenti passaggi: 1) Gli assi sono disegnati, e poi 2) una funzione draw() è chiamato a disegnare i dati. Esistono diverse funzioni draw() per diversi tipi di grafici e la funzione per i grafici a linee è Chart.controllers.line.prototype.draw. Le funzioni draw() accettano un argomento, che chiamerò animationFraction, che indica la completezza dell'animazione come frazione. Ad esempio, se un'animazione è completa al 5%, animationFraction sarà 0,05 e se un'animazione è completa al 100% (ovvero se il grafico è nella sua forma finale), animationFraction=1. La funzione draw() viene richiamata in ogni fase dell'animazione per aggiornare la visualizzazione dei dati.

Una trucco animare l'asse x è quindi di scimmia correggere il grafico a linee draw() funzione di tradurre la tela nella dimensione orizzontale in ogni disegnare passo:

var hShift = (1-animationFraction)*ctx.canvas.width; 

hShift è lo spostamento orizzontale in pixel del grafico. Come sopra definito, i dati scorreranno da destra; se vuoi che scorra da sinistra, puoi rendere negativo il precedente. È quindi salvare lo stato contesto tela, di trasformare la tela utilizzando hShift, disegna i dati del grafico, e quindi ripristinare la tela al suo stato originale in modo che la prossima animazione fotogramma gli assi saranno disegnate nel punto corretto:

ctx.save(); 
ctx.setTransform(1, 0, 0, 1, hShift, 0); 
ctx.oldDraw.call(this, animationFraction); 
ctx.restore(); 

In quanto sopra, this si riferisce all'oggetto grafico e oldDraw si riferisce alla funzione di disegno grafico a linea originale che è stato salvato in precedenza:

var oldDraw = Chart.controllers.line.prototype.draw; 

È possibile inoltre configurare il nuovo draw() funzione per leggere nuove opzioni di animazione che permettono tu per impostare wheth er l'asse xe asse y sono animati:

var oldDraw = Chart.controllers.line.prototype.draw; 
Chart.controllers.line.prototype.draw = function(animationFraction) { 
    var animationConfig = this.chart.options.animation; 
    if (animationConfig.xAxis === true) { 
     var ctx = this.chart.chart.ctx; 
     var hShift = (1-animationFraction)*ctx.canvas.width; 
     ctx.save(); 
     ctx.setTransform(1, 0, 0, 1, hShift,0); 
     if (animationConfig.yAxis === true) { 
      oldDraw.call(this, animationFraction); 
     } else { 
      oldDraw.call(this, 1); 
     } 
     ctx.restore(); 
    } else if (animationConfig.yAxis === true) { 
     oldDraw.call(this, animationFraction); 
    } else { 
     oldDraw.call(this, 1); 
    } 
} 

È quindi possibile creare un grafico linea con entrambi gli assi animati con:

var lineChart = new Chart(ctx, { 
    type: 'line', 
    data: data, 
    options: { 
     animation: { 
      duration: 5000, 
      xAxis: true, 
      yAxis: true, 
     } 
    } 
}); 

Vedere https://jsfiddle.net/16L8sk2p/ per una demo.

Se si desidera animare l'asse X Limiti

Se si desidera animare i limiti dell'asse x - cioè. sposta i dati, le tacche degli assi e le etichette di spunta, quindi puoi utilizzare la seguente strategia. È un po 'bizzarro, quindi potrebbe essere necessario uno sforzo per risolvere i nodi per ogni caso d'uso, ma credo che dovrebbe funzionare in generale. Innanzitutto, è necessario convertire il grafico a linee in un grafico a dispersione. I grafici a linee hanno assi X categoriali che si muovono a passi, quindi non è possibile impostare i limiti degli assi tra i tick, che è quello che devi fare per ottenere l'animazione. Quindi, dovrai utilizzare un grafico a dispersione lineare, poiché i grafici a dispersione possono avere limiti di assi arbitrari. Puoi farlo numerando ogni punto dati e assegnando quel numero al valore x per quel punto dati. Per esempio, per generare un insieme di dati a caso, si potrebbe fare:

var DATA_POINT_NUM = 58; 
var data = { 
    labels: [], 
    datasets: [ 
     { 
      data: [], 
     }, 
    ] 
} 
for (var i=0; i<DATA_POINT_NUM; i++) { 
    data.datasets[0].data.push({ x: i, 
            y: Math.random()*10 
           }); 
    data.labels.push(String.fromCharCode(65+i)); 
} 

Avrete quindi bisogno di scrivere una funzione per la conversione tra i valori x assegnati dei punti di dati e le etichette dei punti dati (vale a dire la categorie che saranno nelle classifiche asse x):

function getXAxisLabel(value) { 
    try { 
     var xMin = lineChart.options.scales.xAxes[0].ticks.min; 
    } catch(e) { 
     var xMin = undefined; 
    } 
    if (xMin === value) { 
     return ''; 
    } else { 
     return data.labels[value]; 
    } 
} 

dove Linechart è il nostro oggetto Chart, che sarà definita di seguito. Nota che ChartJS disegna il grafico in modo leggermente diverso se c'è un'etichetta al valore minimo dell'asse x, quindi dovrai scrivere questa funzione per restituire una stringa vuota se il valore == il valore minimo dell'asse x. È quindi possibile definire l'oggetto Chart:

var lineChart = new Chart(ctx, { 
    type: 'line', 
    data: data, 
    options: { 
     animation: false, 
     scales: { 
      xAxes: [{ 
       type: 'linear', 
       position: 'bottom', 
       ticks: { 
        min: 0, 
        max: 10, 
        callback: getXAxisLabel, // function(value) { return data.labels[value]; }, 
        autoSkip: false, 
        maxRotation: 0, 

       }, 
      }] 
     } 
    } 
}); 

ticks.callback è impostata la nostra funzione getXAxisLabel sopra. Quando ChartJS disegna l'asse x, passerà i valori x dei punti dati alla funzione di callback e quindi utilizzerà la stringa risultante come valore sull'asse x. In questo modo, possiamo disegnare un grafico a dispersione come un grafico a linee. Ho anche impostato autoSkip=false e maxRotation=0 per assicurarmi che le etichette degli assi vengano disegnate in modo coerente.

È quindi possibile animare il grafico regolando i valori dell'asse x ticks.min e ticks.max e chiamando il metodo .update() del grafico. Per illustrare ciò, il codice seguente esegue la scansione lungo l'asse x del grafico, mostrando dieci punti dati alla volta.

var xMin = 0;     // Starting minimum value for the x-axis 
var xLength = 10;    // Length of the x-axis 
var animationDuration = 5000; // Duration of animation in ms 

// Calculate animation properties 
var framesPerSec = 100; 
var frameTime = 1000/framesPerSec; 
var xStep = (DATA_POINT_NUM-xMin+xLength)/(animationDuration/1000*framesPerSec); 

function nextFrame() { 
    var xMax = xMin+xLength; 
    if (xMax < DATA_POINT_NUM-1) { 

     if (xMax+xStep > DATA_POINT_NUM-1) { 
      xMax = DATA_POINT_NUM-1; 
      xMin = xMax-xLength; 
     } 
     lineChart.options.scales.xAxes[0].ticks.min = xMin; 
     lineChart.options.scales.xAxes[0].ticks.max = xMax; 
     lineChart.update(); 
     setTimeout(nextFrame, frameTime); 
     xMin += 0.1; 
    } 
} 

nextFrame(); 

Mettere tutto insieme: https://jsfiddle.net/qLhojncy/

+0

Ora che ho riletto la domanda, non mi sembra chiaro, ma quando ho creato la taglia ciò che stavo cercando era la possibilità di animare le * etichette * sull'asse x, non i dati del grafico nella dimensione x. Non sono sicuro di quale di questi si riferisse il richiedente originale. Puoi vedere un esempio di ciò che intendo in d3 qui facendo clic su "aggiorna" in questo grafico ~ http://bl.ocks.org/d3noob/7030f35b72de721622b8 – Aerovistae

+0

@Aerovistae, vedo. Ho modificato la mia risposta per includere un possibile approccio per l'animazione delle etichette. Spero che funzionerà per te. – cjg

+0

Grazie, questo è perfetto! –

1

Non sono esperto di javascript ma ho trovato un esempio per Chartjs che, quando inserito un nuovo punto dati, aggiorna l'asse x tramite l'animazione come sembra, forse ti aiuta: example.

source Esempio: sitepoint.com

+1

Come il problema afferma che il problema è animare l'asse x su un grafico a linee. –