Библиотека Vivus предназначена для поэтапного «прорисовывания»
SVG-элементов через управление свойствами обводки. Основной механизм
основан на манипуляции stroke-dasharray и
stroke-dashoffset, что позволяет имитировать эффект
рисования линий в реальном времени.
CSS-анимации, в свою очередь, предоставляют декларативный способ управления трансформациями, прозрачностью, фильтрами и частично свойствами обводки. Комбинация этих двух подходов создаёт гибкую систему визуальных эффектов, где JavaScript управляет последовательностью отрисовки, а CSS отвечает за визуальную динамику элементов.
Ключевая идея интеграции заключается в разделении ответственности:
Для корректной работы с Vivus SVG должен содержать пути
(<path>), контуры (<circle>,
<rect> и т.д. при необходимости преобразованные в
paths), а также предсказуемую структуру группировки.
<svg id="logo" viewBox="0 0 200 200">
<g class="logo-group">
<path class="line accent" d="M10 10 L190 10" />
<path class="line accent" d="M190 10 L190 190" />
<path class="line base" d="M190 190 L10 190" />
<path class="line base" d="M10 190 L10 10" />
</g>
</svg>
CSS-классы заранее задают визуальные состояния, которые будут активироваться в процессе анимации.
Vivus предоставляет контроль над стадиями отрисовки через
callback-функции, включая onReady, onFrame, а
также управление скоростью и типом анимации.
const animation = new Vivus('logo', {
type: 'delayed',
duration: 200,
start: 'autostart',
onReady: function (instance) {
document.querySelector('#logo').classList.add('is-loading');
}
});
CSS-класс is-loading задаёт начальное состояние, в
котором элементы подготавливаются к анимации: устанавливаются
прозрачность, масштаб или фильтры размытия.
.is-loading .line {
opacity: 0;
filter: blur(2px);
}
Одним из ключевых приёмов является использование прогресса отрисовки для управления CSS-состояниями.
Vivus позволяет отслеживать текущий шаг анимации через внутренние механизмы, либо косвенно через таймеры и коллбеки.
const logo = new Vivus('logo', {
type: 'oneByOne',
duration: 300,
start: 'autostart',
onFrame: function (step, instance) {
const progress = step / instance.duration;
if (progress > 0.3) {
document.querySelector('.logo-group').classList.add('phase-mid');
}
if (progress > 0.7) {
document.querySelector('.logo-group').classList.add('phase-final');
}
}
});
CSS управляет переходами между фазами:
.logo-group.phase-mid .accent {
stroke: #4f7cff;
transition: stroke 0.6s ease;
}
.logo-group.phase-final .base {
stroke-width: 3;
opacity: 1;
}
Vivus уже использует манипуляцию stroke-dashoffset, но
CSS может дополнительно усиливать эффект через keyframes, создавая
многослойную визуализацию.
.line {
stroke-dasharray: 400;
stroke-dashoffset: 400;
}
После завершения стадии рисования можно запускать CSS-анимацию свечения:
.logo-group.phase-final .line {
animation: glow 1.2s ease-in-out infinite alternate;
}
@keyframes glow {
from {
filter: drop-shadow(0 0 0px rgba(79, 124, 255, 0));
}
to {
filter: drop-shadow(0 0 8px rgba(79, 124, 255, 0.8));
}
}
Таким образом создаётся эффект перехода от «рисования» к «оживлению» объекта.
Vivus добавляет SVG-классы в процессе отрисовки, включая
viven-подобные состояния и внутренние структуры путей. Это
позволяет использовать CSS-селекторы без дополнительного JavaScript.
svg path {
transition: stroke 0.3s ease, opacity 0.3s ease;
}
svg.is-done path {
stroke: #2ecc71;
opacity: 1;
}
JavaScript фиксирует завершение анимации:
const v = new Vivus('logo', {
duration: 250
}, function () {
document.querySelector('#logo').classList.add('is-done');
});
Конфликты между CSS transition и Vivus возникают при одновременном
управлении stroke-dashoffset. Поэтому важно разграничивать
зоны ответственности:
stroke-dashoffsetПример безопасного разделения:
.line {
transition: stroke 0.4s ease, opacity 0.4s ease;
}
new Vivus('logo', {
duration: 180,
type: 'sync'
});
Часто требуется не только прорисовка линий, но и поэтапное появление групп элементов. В этом случае Vivus управляет геометрией, а CSS — структурой отображения.
<g class="layer layer-1">
<path d="..." />
</g>
<g class="layer layer-2">
<path d="..." />
</g>
.layer {
opacity: 0;
transform: translateY(10px);
transition: opacity 0.6s ease, transform 0.6s ease;
}
.layer.visible {
opacity: 1;
transform: translateY(0);
}
const v = new Vivus('logo', {
duration: 220,
onFrame: function (step, instance) {
const p = step / instance.duration;
if (p > 0.2) {
document.querySelector('.layer-1').classList.add('visible');
}
if (p > 0.5) {
document.querySelector('.layer-2').classList.add('visible');
}
}
});
CSS custom properties позволяют связать прогресс анимации с визуальными параметрами.
:root {
--progress-color: #3a3a3a;
}
.line {
stroke: var(--progress-color);
}
JavaScript изменяет переменную в зависимости от состояния Vivus:
onFrame: function (step, instance) {
const progress = step / instance.duration;
document.documentElement.style.setProperty(
'--progress-color',
progress > 0.5 ? '#4f7cff' : '#3a3a3a'
);
}
Это создаёт непрерывный визуальный переход без необходимости сложных CSS-анимаций.
После завершения работы Vivus SVG часто становится частью интерфейса. CSS обеспечивает переход от «анимированного объекта» к «интерактивному элементу».
#logo {
pointer-events: none;
}
#logo.is-active {
pointer-events: auto;
cursor: pointer;
}
new Vivus('logo', {
duration: 200
}, function () {
const svg = document.getElementById('logo');
svg.classList.add('is-active');
});
Для усиления визуального эффекта часто используется наложение нескольких CSS-анимаций на один SVG:
.line {
animation:
pulse 2s ease-in-out infinite,
fadeIn 0.8s ease forwards;
}
@keyframes pulse {
0%, 100% { opacity: 0.7; }
50% { opacity: 1; }
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
Vivus при этом продолжает управлять только отрисовкой контура, не вмешиваясь в CSS-анимации слоёв.
Совмещение SVG-отрисовки и CSS-анимаций требует учёта производительности:
transform и opacity для
CSS-анимацийstroke-width во время активной
отрисовкиblur,
drop-shadow) на каждом кадре Vivuswill-change: transform, opacity для
ускорения рендеринга.layer {
will-change: transform, opacity;
}
Каскадная анимация достигается разделением SVG на логические группы и последовательным включением CSS-состояний по мере продвижения Vivus.
const v = new Vivus('logo', {
type: 'delayed',
duration: 280,
onFrame: function (step, instance) {
const p = step / instance.duration;
document.body.classList.toggle('step-1', p > 0.25);
document.body.classList.toggle('step-2', p > 0.55);
document.body.classList.toggle('step-3', p > 0.85);
}
});
.step-1 .accent { stroke: #ff6b6b; }
.step-2 .accent { stroke: #feca57; }
.step-3 .accent { stroke: #1dd1a1; }
После завершения прорисовки SVG становится полноценным интерактивным объектом. CSS управляет состояниями hover, active и focus:
#logo.is-active:hover .line {
stroke-width: 4;
transition: stroke-width 0.3s ease;
}
Такой подход отделяет анимацию построения формы от пользовательского взаимодействия, сохраняя чистую архитектуру визуального слоя.