Интеграция Vivus в реальный проект начинается с выбора способа
подключения библиотеки и определения того, как именно SVG-анимации будут
управляться в рамках архитектуры приложения. Vivus может использоваться
как автономный модуль, как часть сборки через npm или как UMD-библиотека
в классическом подключении через <script>.
При установке через npm структура проекта обычно предполагает явное управление зависимостями:
npm install vivus
Далее библиотека импортируется в модуль:
import Vivus from 'vivus';
В случаях использования классического подключения:
<script src="vivus.min.js"></script>
В глобальной области появляется Vivus, который можно
использовать напрямую.
Ключевая точка интеграции — создание экземпляра анимации, привязанного к конкретному SVG-элементу:
const animation = new Vivus('svgElementId', {
duration: 200,
type: 'delayed'
});
Первый параметр может быть как идентификатором DOM-элемента, так и самим элементом:
const svg = document.querySelector('.logo');
const animation = new Vivus(svg, {
duration: 150
});
В рамках интеграции с пользовательским кодом важно учитывать момент инициализации DOM. Если SVG создаётся динамически, вызов должен происходить только после вставки элемента в документ.
В современных приложениях SVG часто формируется на лету. В таком случае Vivus должен инициализироваться после полной вставки разметки:
function renderIcon(container) {
container.innerHTML = `
<svg id="dynamicIcon" viewBox="0 0 100 100">
<path d="..." />
</svg>
`;
new Vivus('dynamicIcon', {
duration: 120
});
}
При использовании шаблонизаторов или виртуального DOM важно гарантировать, что реальный DOM уже синхронизирован.
Vivus предоставляет базовые методы управления состоянием анимации, которые удобно встраиваются в пользовательскую логику приложения:
const v = new Vivus('icon', { duration: 200 });
v.stop();
v.play(1);
v.reset();
v.finish();
Интеграция с бизнес-логикой часто строится вокруг этих методов. Например, анимация может запускаться при изменении состояния интерфейса:
button.addEventListener('click', () => {
v.reset();
v.play();
});
Vivus легко связывается с DOM-событиями, что позволяет использовать его как часть реактивного интерфейса:
menu.addEventListener('mouseenter', () => {
iconAnimation.play(1);
});
menu.addEventListener('mouseleave', () => {
iconAnimation.stop().reset();
});
Такой подход часто используется в интерфейсах, где SVG выполняет роль визуального индикатора состояния.
Одним из наиболее частых сценариев является запуск анимации при
появлении элемента в зоне видимости. Для этого используется
IntersectionObserver:
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
animation.play(1);
}
});
});
observer.observe(document.querySelector('#logo'));
Подобная схема исключает лишние вычисления и позволяет масштабировать количество анимаций без потери производительности.
В сложных интерфейсах одновременно существует множество SVG-анимаций. В этом случае важна централизованная логика управления:
const animations = [];
document.querySelectorAll('.animated-svg').forEach((el) => {
animations.push(new Vivus(el, { duration: 100 }));
});
Далее можно реализовать массовое управление:
function playAll() {
animations.forEach(a => a.reset().play());
}
Такой подход часто используется в dashboard-интерфейсах и интерактивных лендингах.
В React интеграция выполняется через useEffect, чтобы
гарантировать наличие DOM:
import { useEffect, useRef } from 'react';
import Vivus from 'vivus';
function Logo() {
const ref = useRef(null);
useEffect(() => {
const animation = new Vivus(ref.current, {
duration: 150
});
return () => animation.stop();
}, []);
return (
<svg ref={ref} viewBox="0 0 100 100">
<path d="..." />
</svg>
);
}
Важно избегать повторной инициализации при каждом рендере, поэтому
зависимости useEffect должны быть пустыми или строго
контролируемыми.
Во Vue интеграция часто выполняется через mounted:
export default {
mounted() {
this.animation = new Vivus(this.$refs.icon, {
duration: 120
});
},
beforeUnmount() {
this.animation.stop();
}
};
Использование ref позволяет напрямую работать с
DOM-узлом без дополнительных запросов.
При использовании Webpack, Vite или Rollup Vivus обычно импортируется как ES-модуль. Однако важно учитывать, что библиотека работает только в браузерной среде, так как зависит от DOM.
Для предотвращения ошибок SSR:
let Vivus;
if (typeof window !== 'undefined') {
Vivus = require('vivus');
}
Или динамический импорт:
useEffect(() => {
import('vivus').then(({ default: Vivus }) => {
new Vivus(svgRef.current, { duration: 100 });
});
}, []);
В архитектурах с централизованным состоянием (Redux, Zustand, Pinia) Vivus может быть частью side-effect слоя.
store.subscribe((state) => {
if (state.logoActive) {
animation.play();
} else {
animation.stop().reset();
}
});
Это позволяет отделить визуальную логику от бизнес-логики и избежать прямых DOM-манипуляций в компонентах.
Если SVG изменяется после первичной отрисовки, Vivus необходимо пересоздать:
function updateSVG(newMarkup) {
container.innerHTML = newMarkup;
animation = new Vivus(container.querySelector('svg'), {
duration: 140
});
}
В сложных интерфейсах требуется предварительное уничтожение старого
экземпляра логически, даже если библиотека не предоставляет явного
destroy.
При масштабировании важно учитывать:
Практика показывает, что группировка анимаций и их ленивый запуск через IntersectionObserver значительно снижает нагрузку.
Vivus часто инкапсулируется в кастомные классы для унификации логики:
class SvgAnimator {
constructor(el, options) {
this.vivus = new Vivus(el, options);
}
play() {
this.vivus.reset().play();
}
stop() {
this.vivus.stop();
}
}
Такая обёртка позволяет интегрировать библиотеку в любую архитектуру без привязки к её API.
Vivus позволяет задавать длительность анимации, но в реальных системах часто требуется синхронизация с внешними событиями:
const duration = userSettings.speed === 'fast' ? 80 : 200;
const animation = new Vivus('icon', {
duration
});
Такой подход связывает визуальную составляющую с параметрами приложения, обеспечивая адаптивное поведение интерфейса.
В приложениях, где SVG зависит от данных API, инициализация Vivus откладывается до завершения загрузки:
fetch('/api/icon')
.then(res => res.text())
.then(svg => {
container.innerHTML = svg;
new Vivus(container.querySelector('svg'), {
duration: 130
});
});
Это позволяет связать визуализацию с серверным контентом без промежуточных состояний.
Для интерфейсов с повторяющимися анимациями важно управлять циклом:
function loopAnimation(v) {
v.reset().play(1);
v.el.addEventListener('animationEnd', () => {
setTimeout(() => v.reset().play(1), 1000);
});
}
Хотя Vivus не предоставляет полноценного event API, контроль можно реализовать через DOM-события или таймеры.
Vivus может работать совместно с CSS-анимациями или GSAP-подобными системами, если разграничить ответственность:
gsap.to(container, {
opacity: 1,
duration: 0.5,
onComplete: () => animation.play()
});
Такой подход позволяет избегать конфликтов между системами анимации.