В Chart.js система анимаций построена вокруг управляемого цикла
перерисовки, в котором каждый рендер кадра проходит через этапы
вычисления промежуточных значений, применения easing-функций и
обновления canvas. В рамках этого процесса предусмотрены коллбеки,
позволяющие внедряться в жизненный цикл анимации — ключевыми из них
являются onProgress и onComplete.
Эти функции относятся к объекту конфигурации
options.animation и выполняются в контексте конкретной
анимации графика. Они позволяют отслеживать ход выполнения анимации и
реагировать на её завершение, не вмешиваясь напрямую в механизм
отрисовки.
Каждая анимация в Chart.js представляет собой последовательность кадров, где:
На каждом шаге система может вызывать пользовательские коллбеки.
onProgress вызывается на каждом шаге анимации, то есть
многократно в процессе её выполнения. Он предоставляет доступ к текущему
состоянию анимации и позволяет отслеживать прогресс в реальном
времени.
В современных версиях Chart.js (v3/v4) callback получает объект состояния:
onProgress: (animation) => {}
Объект animation содержит информацию о текущем
состоянии:
animation.currentStep — текущий шаг анимацииanimation.numSteps — общее количество шаговanimation.chart — ссылка на экземпляр графикаanimation.initial — признак начального состоянияanimation.easing — используемая easing-функцияconst config = {
type: 'line',
data: {
labels: ['A', 'B', 'C', 'D'],
datasets: [{
label: 'Продажи',
data: [10, 25, 15, 40]
}]
},
options: {
animation: {
duration: 2000,
easing: 'easeOutQuart',
onProgress: (animation) => {
const progress = animation.currentStep / animation.numSteps;
const chart = animation.chart;
chart.options.plugins.title = {
display: true,
text: `Прогресс анимации: ${(progress * 100).toFixed(0)}%`
};
}
}
}
};
В данном случае каждый кадр анимации изменяет состояние заголовка
графика в зависимости от прогресса. Это демонстрирует, что
onProgress может использоваться для синхронизации
интерфейса с отрисовкой графика.
Повторяющийся характер вызова накладывает ограничения:
onComplete вызывается один раз после завершения всей
анимации. Он срабатывает, когда currentStep достигает
numSteps, и все элементы графика завершили переход в
конечное состояние.
onComplete: (animation) => {}
Объект animation аналогичен используемому в
onProgress, но в момент вызова анимация уже завершена.
const config = {
type: 'bar',
data: {
labels: ['Q1', 'Q2', 'Q3'],
datasets: [{
label: 'Доход',
data: [30, 50, 80]
}]
},
options: {
animation: {
duration: 1500,
onComplete: (animation) => {
const chart = animation.chart;
chart.options.plugins.legend.labels.color = 'black';
chart.update();
}
}
}
};
Здесь после завершения анимации изменяется стиль легенды и выполняется обновление графика.
Поведение обоих коллбеков определяется моментом их вызова внутри анимационного цикла:
| Коллбек | Момент вызова | Частота | Назначение |
|---|---|---|---|
| onProgress | каждый кадр анимации | многократно | отслеживание состояния |
| onComplete | завершение анимации | один раз | финализация состояния |
Оба коллбека получают объект, содержащий ссылку на экземпляр графика:
animation.chart
Через него доступно:
chart.data)chart.options)chart.update())Использование этой ссылки позволяет синхронизировать анимацию с внешними событиями интерфейса или логикой приложения.
let loading = true;
const config = {
type: 'line',
data: {
labels: ['Jan', 'Feb', 'Mar'],
datasets: [{
label: 'Трафик',
data: [120, 90, 140]
}]
},
options: {
animation: {
duration: 3000,
onProgress: (animation) => {
loading = true;
},
onComplete: (animation) => {
loading = false;
const chart = animation.chart;
chart.data.datasets[0].borderWidth = 3;
chart.update();
}
}
}
};
В данном сценарии состояние загрузки привязывается к жизненному циклу анимации, а финальная стилизация применяется только после её завершения.
Вызов chart.update() внутри onProgress или
onComplete может приводить к повторному запуску анимации,
если не учитывать параметры обновления. В Chart.js предусмотрены режимы
обновления:
'none' — без анимации'active' — частичное обновление'resize' — перерасчёт размеров'normal' — стандартное обновлениеПример безопасного обновления после завершения:
onComplete: (animation) => {
animation.chart.update('none');
}
Для снижения нагрузки применяются следующие подходы:
update() внутри
onProgressВ сложных графиках с несколькими datasets каждая анимация может иметь
свой жизненный цикл. В таких случаях onProgress и
onComplete отражают состояние всей анимации графика, а не
отдельных элементов.
options: {
animation: {
onProgress: (animation) => {
const { numSteps, currentStep } = animation;
},
onComplete: (animation) => {
const chart = animation.chart;
}
}
}
Если параметр:
animation: false
то:
onProgress не вызывается,onComplete не вызывается,Коллбеки анимации часто используются совместно с плагинами, например:
Плагины могут использовать данные анимации, переданные через
animation.chart и синхронизировать собственные рендеры с
прогрессом анимации.