Vivus реализует анимацию SVG-путей через последовательное «прорисовывание» линий, имитируя эффект ручного рисования. Архитектура библиотеки построена вокруг жизненного цикла анимации, где ключевую роль играют события, позволяющие синхронизировать внешнюю логику с этапами отрисовки.
Событийная модель в Vivus не является полноценной системой EventEmitter, как в DOM или Node.js. Вместо этого используется набор callback-функций, передаваемых через конфигурацию или вызываемых внутри экземпляра анимации. Несмотря на простоту, эта модель покрывает основные стадии жизненного цикла SVG-анимации и позволяет строить сложные сценарии управления визуальными эффектами.
Анимация SVG в Vivus проходит несколько логических этапов:
<path>,
<line>, <polyline> и др.)Каждый этап может быть перехвачен через соответствующие события.
| Событие / Callback | Момент вызова | Описание | Параметры |
|---|---|---|---|
onReady |
После инициализации SVG и подготовки путей | Срабатывает, когда SVG полностью загружен и готов к анимации, но до старта отрисовки | vivusInstance |
onStart |
В момент запуска анимации | Вызывается один раз при начале анимационного цикла | vivusInstance |
onProgress |
На каждом шаге анимации | Срабатывает при каждом изменении прогресса от 0 до 1 | progress, vivusInstance |
onEnd |
После завершения анимации | Вызывается один раз после достижения конца анимации | vivusInstance |
onFrame (внутренний/пользовательский паттерн) |
На каждом кадре requestAnimationFrame | Используется в кастомных сборках или расширениях поверх Vivus | frameData |
Событие подготовки играет ключевую роль в архитектуре Vivus. На этом этапе происходит разбор DOM-структуры SVG и подготовка всех путей к анимации.
Типичные операции внутри этого этапа:
getTotalLength()stroke-dasharray и
stroke-dashoffsetСостояние onReady означает, что объект Vivus полностью
готов к запуску, но визуально ещё не изменён.
Пример логики обработки:
new Vivus('svg-id', {
type: 'delayed',
duration: 200,
onReady: function (instance) {
instance.el.setAttribute('data-state', 'ready');
}
});
На этом этапе можно безопасно изменять стили, не влияя на анимационный процесс.
Событие старта фиксирует момент, когда начинается первый шаг
изменения stroke-dashoffset. Оно вызывается единожды за
жизненный цикл анимации.
Особенности:
onReadyПример применения:
new Vivus('svg-id', {
duration: 150,
onStart: function (instance) {
document.body.classList.add('animation-running');
}
});
Важный момент заключается в том, что onStart не зависит
от текущего прогресса и всегда инициируется перед первым изменением
состояния SVG.
Событие прогресса является наиболее часто используемым. Оно позволяет отслеживать текущее состояние анимации в диапазоне от 0 до 1.
В зависимости от режима (delayed, sync,
oneByOne) прогресс может изменяться линейно или
ступенчато.
Пример использования:
new Vivus('svg-id', {
duration: 300,
onProgress: function (progress, instance) {
const percent = Math.floor(progress * 100);
document.querySelector('#percent').textContent = percent + '%';
}
});
requestAnimationFrameСобытие часто применяется для:
Событие завершения фиксирует момент, когда все SVG-пути полностью отрисованы.
Поведение:
Пример:
new Vivus('svg-id', {
duration: 200,
onEnd: function (instance) {
instance.el.classList.add('completed');
}
});
Часто применяется для:
Событийная последовательность строго определена:
onReadyonStartonProgress (многократно)onEndЭта цепочка формирует предсказуемый жизненный цикл, позволяющий строить сложные композиции анимаций.
new Vivus('svg-id', {
duration: 250,
onReady: function (instance) {
instance.el.style.opacity = 1;
},
onStart: function () {
console.log('start');
},
onProgress: function (p) {
console.log('progress:', p);
},
onEnd: function () {
console.log('end');
}
});
Система событий Vivus имеет несколько технических особенностей:
Все события реализованы как callbacks в конфигурации, а не через подписку:
.on() или .emit()Каждый callback получает доступ к текущему экземпляру Vivus, что позволяет:
onProgress синхронизирован с циклом браузера:
Событие onEnd часто используется для последовательного
запуска анимаций:
const first = new Vivus('svg-1', {
duration: 120,
onEnd: function () {
second.play();
}
});
const second = new Vivus('svg-2', {
duration: 120
});
new Vivus('svg-id', {
onProgress: function (p, instance) {
instance.el.style.filter = `blur(${(1 - p) * 5}px)`;
}
});
new Vivus('svg-id', {
onStart: function () {
loader.hidden = false;
},
onProgress: function (p) {
loader.value = p;
},
onEnd: function () {
loader.hidden = true;
}
});
Несмотря на удобство, модель имеет ограничения:
Эти ограничения компенсируются простотой и предсказуемостью поведения, что важно для SVG-анимаций в браузере.