Прогресс-бары

SVG-прогресс-бары на основе SVG представляют собой один из наиболее гибких способов визуализации загрузки, выполнения операций и состояния процессов в интерфейсе. В отличие от растровых индикаторов, такие элементы сохраняют чёткость на любых разрешениях и позволяют точно управлять анимацией через JavaScript. Использование Vivus добавляет к этому контролируемую отрисовку SVG-пути, создавая эффект «рисования» прогресс-бара в реальном времени.

SVG-прогресс-бар строится вокруг базового принципа: линия или контур, длина которого визуально отражает степень выполнения задачи. В основе лежит элемент <path>, геометрия которого может быть прямой линией, дугой или сложной фигурой.

Ключевое свойство SVG, используемое для анимации прогресса:

  • stroke-dasharray — задаёт длину штрихов и пробелов
  • stroke-dashoffset — смещает начало отображаемой части линии

Манипулируя этими параметрами, можно «скрывать» часть линии и постепенно раскрывать её по мере увеличения прогресса.

Для вычисления полной длины пути используется метод:

path.getTotalLength()

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

Vivus и принцип отрисовки SVG

Vivus — библиотека, ориентированная на анимацию SVG-путей через последовательное изменение stroke-dashoffset. Она позволяет создавать эффект рисования элементов без ручного управления каждой точкой пути.

Инициализация базируется на объекте:

new Vivus('svgElementId', {
  type: 'delayed',
  duration: 200,
  start: 'autostart'
});

Основные параметры:

  • type — стратегия анимации
  • duration — длительность анимации
  • start — способ запуска (авто или вручную)

Vivus работает напрямую с DOM SVG, разбивая пути на сегменты и изменяя их состояние по кадрам.

Типы анимации Vivus для прогресс-баров

delayed

Каждый SVG-путь анимируется с небольшой задержкой относительно предыдущего. В контексте прогресс-баров создаёт эффект последовательного заполнения сегментов.

new Vivus('progressSvg', {
  type: 'delayed',
  duration: 150
});

Использование этого режима оправдано для сложных индикаторов, состоящих из нескольких частей.

sync

Все пути анимируются одновременно. Подходит для линейных прогресс-баров, где требуется равномерное заполнение.

new Vivus('progressSvg', {
  type: 'sync',
  duration: 100
});

Этот режим ближе всего к классическому пониманию прогресс-бара.

oneByOne

Элементы SVG отрисовываются последовательно, один за другим. При применении к индикаторам создаёт эффект «рисующейся линии прогресса».

new Vivus('progressSvg', {
  type: 'oneByOne',
  duration: 200
});

Используется для сложных визуальных сценариев, где прогресс представлен как маршрут или траектория.

Построение линейного SVG-прогресс-бара

Базовый вариант прогресс-бара представляет собой прямую линию <line> или простой <path>.

Пример SVG:

<svg id="progressSvg" width="300" height="20">
  <path d="M10 10 L290 10" stroke="#4caf50" stroke-width="6" fill="none"/>
</svg>

При подключении Vivus линия начинает «рисоваться» от начала к концу, создавая визуальный эффект заполнения.

Прогресс-бар на основе длины пути

Для точного управления прогрессом без автоматической анимации Vivus можно комбинировать с ручным контролем stroke-dashoffset.

Алгоритм:

  1. Получить длину пути
  2. Установить её как stroke-dasharray
  3. Менять stroke-dashoffset в зависимости от процента
const path = document.querySelector('#progressSvg path');
const length = path.getTotalLength();

path.style.strokeDasharray = length;
path.style.strokeDashoffset = length;

Далее прогресс вычисляется:

function setProgress(percent) {
  const offset = length - (percent / 100) * length;
  path.style.strokeDashoffset = offset;
}

Vivus может использоваться параллельно, чтобы анимировать появление пути, а затем управление передаётся логике прогресса.

Комбинирование Vivus и динамического прогресса

Vivus выполняет роль первичной анимации появления, после чего SVG становится интерактивным индикатором.

const vivus = new Vivus('progressSvg', {
  type: 'sync',
  duration: 120
}, () => {
  enableProgressControl();
});

После завершения анимации активируется управление значением прогресса через JavaScript.

Круговые прогресс-бары

SVG позволяет строить не только линейные индикаторы, но и круговые, основанные на окружности <circle>.

<svg id="circleProgress" width="120" height="120">
  <circle cx="60" cy="60" r="50" stroke="#ddd" stroke-width="8" fill="none"/>
  <circle cx="60" cy="60" r="50" stroke="#4caf50" stroke-width="8" fill="none"/>
</svg>

Длина окружности:

const circle = document.querySelector('#circleProgress circle:nth-child(2)');
const radius = 50;
const circumference = 2 * Math.PI * radius;

Настройка:

circle.style.strokeDasharray = `${circumference} ${circumference}`;
circle.style.strokeDashoffset = circumference;

Прогресс:

function setCircleProgress(percent) {
  const offset = circumference - (percent / 100) * circumference;
  circle.style.strokeDashoffset = offset;
}

Vivus в данном случае может анимировать начальную прорисовку окружности, после чего управление берёт логика состояния.

Управление анимацией Vivus

Vivus предоставляет набор методов для контроля процесса:

  • play() — запуск или продолжение анимации
  • stop() — остановка
  • reset() — сброс в исходное состояние
  • finish() — мгновенное завершение анимации
const v = new Vivus('progressSvg', {
  duration: 150,
  start: 'manual'
});

v.play();
v.stop();
v.reset();
v.finish();

Для прогресс-баров finish() часто используется для мгновенного перехода к 100%.

Интерактивные прогресс-индикаторы

SVG-прогресс-бары с Vivus часто используются в интерфейсах загрузки файлов и API-запросов. В таких сценариях визуальная часть отделяется от реального состояния процесса.

Пример логики:

function simulateLoading(vivusInstance) {
  let progress = 0;

  const interval = setInterval(() => {
    progress += 2;

    setProgress(progress);

    if (progress >= 100) {
      clearInterval(interval);
      vivusInstance.finish();
    }
  }, 100);
}

Многоуровневые SVG-индикаторы

Сложные интерфейсы используют несколько путей в одном SVG:

  • основной прогресс
  • вторичный фон
  • индикатор сегментов
  • декоративные элементы

Vivus анимирует каждый путь отдельно, что позволяет создавать многослойные эффекты загрузки.

<svg id="multiProgress">
  <path class="bg" d="..." />
  <path class="progress" d="..." />
  <path class="ticks" d="..." />
</svg>
new Vivus('multiProgress', {
  type: 'oneByOne',
  duration: 200
});

Оптимизация SVG для прогресс-анимации

Для стабильной работы анимаций важны следующие аспекты:

  • минимизация количества узлов <path>
  • упрощение кривых без потери формы
  • использование единых stroke-параметров
  • избегание лишних фильтров SVG

Сложные кривые увеличивают нагрузку на перерасчёт длины пути, что влияет на плавность анимации Vivus.

Синхронизация с внешними событиями

Прогресс-бары часто привязываются к событиям:

  • загрузка файлов
  • выполнение API-запросов
  • шаги мастера интерфейса
  • обработка данных

Пример:

fetch('/upload')
  .then(res => res.json())
  .then(() => setProgress(100));

Vivus при этом используется для начальной анимации появления индикатора, создавая визуальную подготовку интерфейса к отображению состояния процесса.