Комбинирование с CSS-анимацией

Библиотека Vivus предназначена для поэтапного «прорисовывания» SVG-элементов через управление свойствами обводки. Основной механизм основан на манипуляции stroke-dasharray и stroke-dashoffset, что позволяет имитировать эффект рисования линий в реальном времени.

CSS-анимации, в свою очередь, предоставляют декларативный способ управления трансформациями, прозрачностью, фильтрами и частично свойствами обводки. Комбинация этих двух подходов создаёт гибкую систему визуальных эффектов, где JavaScript управляет последовательностью отрисовки, а CSS отвечает за визуальную динамику элементов.

Ключевая идея интеграции заключается в разделении ответственности:

  • Vivus управляет порядком и прогрессом отрисовки SVG-путей
  • CSS управляет состояниями внешнего вида элементов на каждом этапе

Базовая структура SVG для комбинированной анимации

Для корректной работы с 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 с синхронизацией 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);
}

Синхронизация прогресса Vivus с CSS-переходами

Одним из ключевых приёмов является использование прогресса отрисовки для управления 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;
}

Комбинация stroke-анимаций и CSS keyframes

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 для управления стадиями

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-анимации

Конфликты между CSS transition и Vivus возникают при одновременном управлении stroke-dashoffset. Поэтому важно разграничивать зоны ответственности:

  • Vivus управляет только stroke-dashoffset
  • CSS управляет цветом, фильтрами, прозрачностью, толщиной линий

Пример безопасного разделения:

.line {
  transition: stroke 0.4s ease, opacity 0.4s ease;
}
new Vivus('logo', {
  duration: 180,
  type: 'sync'
});

Анимация появления групп SVG через CSS и Vivus

Часто требуется не только прорисовка линий, но и поэтапное появление групп элементов. В этом случае 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 variables для динамики цвета

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-анимаций.


Переход от draw-анимации к UI-анимации

После завершения работы 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-анимации

Для усиления визуального эффекта часто используется наложение нескольких 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) на каждом кадре Vivus
  • использование will-change: transform, opacity для ускорения рендеринга
.layer {
  will-change: transform, opacity;
}

Сценарии каскадной анимации через CSS и Vivus

Каскадная анимация достигается разделением 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; }

Связка интерактивных состояний CSS и завершённой анимации Vivus

После завершения прорисовки SVG становится полноценным интерактивным объектом. CSS управляет состояниями hover, active и focus:

#logo.is-active:hover .line {
  stroke-width: 4;
  transition: stroke-width 0.3s ease;
}

Такой подход отделяет анимацию построения формы от пользовательского взаимодействия, сохраняя чистую архитектуру визуального слоя.