2016-07-03 21 views
10

Chcę użyć linechart chartjs do wizualizacji moich punktów danych. Chartjs wydaje się domyślnie animować wykres, ale nie animuje wartości na osi X. Oś X porusza się tylko w dyskretnych krokach.Chartjs animacja oś x

Czy jest jakiś sposób włączenia animacji na osi?

Dzięki!

+0

nie jest jasne, czy były prośbą o animowaniu danych wykres w wymiaru X jako CTG zrobiła poniżej lub jeśli oznaczało animowanie etykiety na X- topory (to jest to, co wziąłem pod uwagę twoje pytanie, i to jest to, czego szukałem, gdy stworzyłem nagrodę), których tutaj nie ma odpowiedzi. Czy mógłbyś wyjaśnić? – Aerovistae

Odpowiedz

4

O ile mi wiadomo, ChartJS nie obsługuje animacji osi x out-of-the-box. Więc musisz to zhackować. Istnieje kilka sposobów, aby to zrobić, ale poniższe metody wydają się działać.

Jeśli chcesz animować dane na oś X

Gdy wykres jest aktualizowany, następujące kroki wystąpić: 1) Osie są opracowywane, a następnie 2) draw() funkcja nazywa się narysuj dane. Dostępne są różne funkcje draw() dla różnych typów wykresów, a funkcja dla wykresów liniowych to Chart.controllers.line.prototype.draw. Funkcje draw() przyjmują jeden argument, który nazywam animationFraction, który wskazuje, w jakim stopniu animacja jest ułamkiem. Na przykład, jeśli animacja jest ukończona w 5%, animationFraction będzie miała wartość 0,05, a jeśli animacja jest w 100% ukończona (to znaczy, jeśli wykres jest w ostatecznej postaci), animationFraction=1. Funkcja draw() jest wywoływana na każdym etapie animacji, aby zaktualizować wyświetlanie danych.

Jeden Hack animowanie osi x, a następnie jest małpa patch wykres liniowy draw() funkcję translacji obszar roboczy w kierunku poziomym, na każdym zwrócić krok:

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

hShift jest poziome przesunięcie pikseli wykresu. Jak zdefiniowano powyżej, dane zmienią się z prawej strony; jeśli chcesz, aby przemykał od lewej strony, możesz uczynić powyższy wynik negatywny. Następnie zapisać stan kontekstowe płótno, przekształcić płótna korzystając hShift, rysować dane wykresu, a następnie przywrócić płótno do stanu pierwotnego, tak że na następnej animacji wrobić osie zostaną sporządzone w odpowiednim miejscu:

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

W powyższym this odnosi się do obiektu wykresu i oldDraw odnosi się do pierwotnej funkcji rysowania wykresu liniowego, który został zapisany wcześniej:

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

można dodatkowo skonfigurować swoją nową draw() funkcja czytać nowe opcje animacji, które pozwalają aby ustawić wheth er oś X i oś Y są animowane:

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); 
    } 
} 

Następnie można utworzyć wykres liniowy z animowanych z obu osiach:

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

Zobacz https://jsfiddle.net/16L8sk2p/ na demo.

Jeśli chcesz animować X-Axis Limits

Jeśli chcesz animować granic oś x - tj. przenieś dane, tyknięcia osi i etykiety zaznaczenia, a następnie możesz zastosować następującą strategię. To trochę dziwaczne, więc może zająć trochę wysiłku, aby wypracować kręgi dla dowolnego przypadku użycia, ale uważam, że powinno działać ogólnie. Najpierw musisz przekonwertować wykres liniowy na wykres punktowy. Wykresy liniowe mają kategoryczne osie x, które poruszają się w krokach, więc nie można ustawić granic osi pomiędzy tykami, co jest potrzebne, aby uzyskać animację. Będziesz musiał użyć wykresu rozproszenia liniowego, ponieważ wykresy rozproszenia mogą mieć dowolne ograniczenia osi. Możesz to zrobić, numerując każdy punkt danych i przypisując ten numer do wartości x dla tego punktu danych. Na przykład, aby wygenerować losowy zbiór danych, można zrobić:

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)); 
} 

Będziesz wtedy trzeba napisać funkcję do konwersji przypisanych wartości x swoich punktów danych oraz etykiet punktów danych (czyli kategorie, które będą na wykresach osi 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]; 
    } 
} 

gdzie lineChart jest naszym obiektem Chart, który zostanie zdefiniowany poniżej. Zauważ, że ChartJS rysuje wykres nieco inaczej, jeśli istnieje etykieta na minimalnej wartości osi x, więc musisz napisać tę funkcję, aby zwrócić pusty ciąg znaków, jeśli wartość == minimalna wartość osi x. Następnie można zdefiniować obiekt wykresu:

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 jest ustawiona na naszej getXAxisLabel funkcji powyżej. Kiedy ChartJS rysuje oś X, przekaże wartości x punktów danych do funkcji wywołania zwrotnego, a następnie użyje wynikowego ciągu jako wartości na osi X. W ten sposób możemy narysować wykres rozproszenia jak wykres liniowy. Ustawiłem też autoSkip=false i maxRotation=0, aby upewnić się, że etykiety osi są rysowane w spójny sposób.

Następnie można animować wykres, dostosowując wartości osi X: ticks.min i ticks.max i wywołując metodę z tabeli .update(). Aby to zilustrować, poniższy kod skanuje wzdłuż osi wykresu, pokazując dziesięć punktów danych na raz.

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(); 

Kładzenie to wszystko razem: https://jsfiddle.net/qLhojncy/

+0

Teraz, gdy ponownie przeczytałem pytanie, wydaje się to niejasne, ale kiedy stworzyłem nagrodę, to czego szukałem, to możliwość animowania * etykiet * na osi X, a nie danych graficznych w wymiarze x. Nie jestem pewien, do którego z nich odnosi się pierwotny pytający. Możesz zobaczyć przykład tego, co mam na myśli w d3, klikając "aktualizuj" na tym wykresie ~ http://bl.ocks.org/d3noob/7030f35b72de721622b8 – Aerovistae

+0

@Aerovistae, rozumiem. Zmieniłem moją odpowiedź, aby uwzględnić jedno z możliwych sposobów animowania etykiet. Mam nadzieję, że to zadziała dla Ciebie. – cjg

+0

Dzięki, to jest idealne! –

1

Nie jestem ekspertem od javascript, ale znalazłem przykład dla Chartjs, który po wstawieniu nowego punktu danych aktualizuje oś X za pomocą animacji, jak się wydaje, może to pomaga: example.

Przykład źródło: sitepoint.com

+1

Problem polega na tym, że problem polega na animowaniu osi X na wykresie liniowym. –