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/
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