Взаимодействие анимации SVG с пользовательскими событиями строится вокруг управления экземпляром Vivus через стандартные DOM-события. Основная идея заключается в том, что анимация не запускается автоматически при загрузке страницы, а привязывается к состоянию наведения курсора на элемент.
Базовая структура работы строится вокруг создания экземпляра:
const icon = new Vivus('icon-svg', {
type: 'delayed',
duration: 120,
start: 'manual'
});
Ключевой момент — параметр start: 'manual', который
отключает автоматический запуск и позволяет полностью контролировать
момент начала отрисовки.
Наиболее распространённый сценарий — запуск анимации при наведении курсора и сброс при уходе.
const icon = new Vivus('icon-svg', {
type: 'oneByOne',
duration: 100,
start: 'manual'
});
const element = document.getElementById('icon-svg');
element.addEventListener('mouseenter', () => {
icon.reset().play();
});
element.addEventListener('mouseleave', () => {
icon.stop().reset();
});
Комбинация методов обеспечивает предсказуемое поведение:
reset() возвращает SVG в исходное состояниеplay() запускает анимацию зановоstop() прерывает текущее воспроизведениеПри частых входах и выходах курсора важно учитывать, что Vivus не
кэширует прогресс как временное состояние UI. Каждый
reset() полностью очищает текущую отрисовку.
Для более плавного UX применяется стратегия «возврата к последнему состоянию»:
element.addEventListener('mouseenter', () => {
icon.stop();
icon.play();
});
В этом случае не выполняется принудительный сброс, а текущая позиция анимации просто прерывается и продолжается заново.
Поведение hover-эффектов сильно зависит от выбранного типа отрисовки.
Каждый путь SVG анимируется с небольшой задержкой:
new Vivus('icon', {
type: 'delayed',
duration: 140,
start: 'manual'
});
Такой вариант создаёт эффект последовательного проявления линий при наведении.
Каждый контур отрисовывается по очереди:
new Vivus('icon', {
type: 'oneByOne',
duration: 90,
start: 'manual'
});
Подходит для интерфейсных иконок, где важна читаемость процесса отрисовки.
Все линии анимируются одновременно:
new Vivus('icon', {
type: 'sync',
duration: 80,
start: 'manual'
});
Используется для быстрых hover-эффектов без визуальной задержки.
Вместо прямой работы с событиями возможно использование CSS-классов как триггера логики:
const icon = new Vivus('icon-svg', {
type: 'sync',
duration: 100,
start: 'manual'
});
const element = document.getElementById('icon-svg-container');
element.addEventListener('mouseenter', () => {
element.classList.add('active');
icon.reset().play();
});
element.addEventListener('mouseleave', () => {
element.classList.remove('active');
icon.stop().reset();
});
Такой подход упрощает интеграцию с системами дизайна и позволяет синхронизировать анимацию с визуальными стилями через CSS.
При наличии группы иконок требуется отдельный экземпляр Vivus для каждого элемента:
document.querySelectorAll('.icon').forEach((el) => {
const instance = new Vivus(el.id, {
type: 'delayed',
duration: 100,
start: 'manual'
});
el.addEventListener('mouseenter', () => {
instance.reset().play();
});
el.addEventListener('mouseleave', () => {
instance.stop().reset();
});
});
Основная особенность — отсутствие разделяемого состояния между экземплярами. Каждый SVG управляется независимо, что снижает риск конфликтов при параллельных hover-событиях.
При интенсивном движении курсора возможны множественные вызовы
mouseenter и mouseleave. Для предотвращения
избыточных перезапусков анимации применяется проверка состояния:
let isPlaying = false;
element.addEventListener('mouseenter', () => {
if (isPlaying) return;
isPlaying = true;
icon.reset().play(() => {
isPlaying = false;
});
});
Callback в play() позволяет точно определить момент
завершения анимации.
Метод stop() не сбрасывает прогресс, а лишь
останавливает текущее воспроизведение. Это используется для создания
эффекта «заморозки» при уходе курсора:
element.addEventListener('mouseleave', () => {
icon.stop();
});
При повторном наведении анимация стартует заново или продолжается в
зависимости от вызова reset().
Для уменьшения случайных срабатываний используется таймер:
let hoverTimer;
element.addEventListener('mouseenter', () => {
hoverTimer = setTimeout(() => {
icon.reset().play();
}, 120);
});
element.addEventListener('mouseleave', () => {
clearTimeout(hoverTimer);
icon.stop().reset();
});
Такая схема предотвращает запуск анимации при кратковременном прохождении курсора над элементом.
При большом количестве SVG-элементов применяется делегирование:
document.body.addEventListener('mouseenter', (e) => {
if (!e.target.classList.contains('vivus-icon')) return;
const id = e.target.id;
const instance = vivusRegistry[id];
instance.reset().play();
}, true);
Использование capture-фазы (true) позволяет
перехватывать событие на этапе входа курсора.
На сенсорных устройствах hover отсутствует, поэтому используется
touchstart:
element.addEventListener('touchstart', () => {
icon.reset().play();
});
Дополнительно учитывается предотвращение двойного срабатывания:
element.addEventListener('touchstart', (e) => {
e.preventDefault();
icon.reset().play();
});
Hover-анимации часто зависят от состояния интерфейса, например активности кнопки или вкладки:
if (!button.disabled) {
element.addEventListener('mouseenter', () => {
icon.play();
});
}
При изменении состояния UI анимация может быть деактивирована полностью:
function setDisabled(state) {
if (state) {
icon.stop().reset();
element.classList.add('disabled');
}
}
Для повторной активации без пересоздания экземпляра используется циклический сброс:
element.addEventListener('mouseleave', () => {
icon.stop();
icon.reset();
});
Такой подход позволяет многократно запускать одну и ту же SVG-анимацию без утечек состояния и лишних перерасходов памяти.