Анимации обводки в SVG основаны на управлении параметрами контура:
stroke-dasharray и stroke-dashoffset. Эти
свойства позволяют имитировать эффект постепенного прорисовывания линии,
когда путь как будто рисуется от начала до конца.
Ключевая идея заключается в том, что обводка разбивается на чередующиеся сегменты: видимые и скрытые. Управляя смещением маски, можно «сдвигать» видимую часть вдоль контура.
SVG-путь можно представить как непрерывную линию фиксированной длины. Для управления её отображением используются два параметра:
stroke-dasharray — определяет шаблон штрихов (длина
видимых и скрытых сегментов)stroke-dashoffset — смещает начало шаблона вдоль
путиЕсли задать:
stroke-dasharray = Lstroke-dashoffset = Lлиния становится полностью скрытой. При анимации
stroke-dashoffset от L до 0
создаётся эффект постепенного появления линии.
Motion One предоставляет минималистичный API для анимаций, включая
SVG-атрибуты. В отличие от более тяжёлых решений, библиотека опирается
на нативные браузерные возможности: requestAnimationFrame,
CSS transforms и SVG presentation attributes.
Основная функция — animate():
import { animate } from "motion"
Она позволяет анимировать как CSS-свойства, так и SVG-атрибуты напрямую.
Для корректной работы эффекта рисования необходимо учитывать структуру path:
<svg viewBox="0 0 200 200">
<path
d="M10 100 C 40 10, 65 10, 95 80 S 150 150, 180 100"
stroke="black"
fill="none"
stroke-width="2"
/>
</svg>
Ключевое требование — отсутствие заливки (fill="none"),
так как анимация касается только обводки.
Для создания эффекта рисования требуется знать полную длину пути. Это делается через метод:
const path = document.querySelector("path")
const length = path.getTotalLength()
Полученное значение используется для настройки dash-параметров.
Простейший эффект прорисовки реализуется через анимацию
strokeDashoffset:
import { animate } from "motion"
const path = document.querySelector("path")
const length = path.getTotalLength()
path.style.strokeDasharray = length
path.style.strokeDashoffset = length
animate(path, { strokeDashoffset: 0 }, { duration: 2 })
В этом сценарии Motion One интерполирует числовое значение от
length до 0, создавая эффект рисования
линии.
Изменение направления анимации достигается инверсией значений:
path.style.strokeDasharray = length
path.style.strokeDashoffset = 0
animate(path, { strokeDashoffset: length }, { duration: 2 })
Таким образом линия «стирается» вместо рисования.
Motion One поддерживает альтернативный подход — использование
pathLength, который абстрагирует работу с реальной длиной
SVG.
animate(path, { pathLength: [0, 1] }, { duration: 2 })
В этом случае библиотека автоматически нормализует длину пути,
переводя значения в диапазон от 0 до 1. Это упрощает работу и устраняет
необходимость вызова getTotalLength().
Преимущества:
Недостатки:
Преимущества:
Недостатки:
Motion One предоставляет встроенные функции сглаживания движения. Они влияют на скорость прорисовки линии.
import { animate, easeInOut } from "motion"
animate(
path,
{ strokeDashoffset: 0 },
{
duration: 2,
easing: easeInOut
}
)
Разные easing-функции создают различное восприятие рисования:
SVG часто содержит несколько path-элементов. Motion One позволяет управлять ими независимо или группировать анимации.
const paths = document.querySelectorAll("path")
paths.forEach((path, index) => {
const length = path.getTotalLength()
path.style.strokeDasharray = length
path.style.strokeDashoffset = length
animate(
path,
{ strokeDashoffset: 0 },
{ duration: 1.5, delay: index * 0.2 }
)
})
Такая схема создаёт эффект последовательного рисования сложной графики.
SVG-анимации часто комбинируются с трансформациями для усиления визуального эффекта.
animate(
path,
{
strokeDashoffset: 0,
scale: [0.9, 1]
},
{
duration: 2
}
)
Совмещение трансформации и прорисовки позволяет создать эффект появления объекта из линии.
Motion One поддерживает управление прогрессом через контролируемые анимации.
const animation = animate(
path,
{ strokeDashoffset: 0 },
{ duration: 3, autoplay: false }
)
animation.currentTime = 1500
Такой подход позволяет синхронизировать stroke-анимации с прокруткой страницы или внешними событиями.
Stroke-анимации часто используются для иллюстраций, реагирующих на прокрутку.
import { animate, scroll } from "motion"
scroll(
animate(path, { strokeDashoffset: 0 }),
{ target: path }
)
В этом режиме прогресс анимации зависит от позиции элемента в viewport.
Сложные иллюстрации часто состоят из нескольких слоёв:
Каждый слой можно анимировать с разными параметрами:
animate(primaryPath, { strokeDashoffset: 0 }, { duration: 2 })
animate(secondaryPath, { strokeDashoffset: 0 }, { duration: 2.5, delay: 0.3 })
Разница в таймингах создаёт ощущение глубины и сложности рисунка.
SVG stroke-анимации чувствительны к количеству узлов в path. Чем больше сегментов, тем выше нагрузка на перерисовку.
Практика оптимизации:
pathLength вместо вычислений длиныMotion One минимизирует накладные расходы, но сложность SVG остаётся критическим фактором.
Дополнительный слой выразительности достигается через комбинирование обводки и прозрачности.
animate(
path,
{
strokeDashoffset: 0,
opacity: [0, 1]
},
{
duration: 1.8
}
)
Появление линии становится более мягким и менее механическим.
Stroke-анимации могут использоваться не только для рисования, но и для стирания:
animate(
path,
{ strokeDashoffset: length },
{ duration: 2 }
)
Такой подход применяется в интерфейсах для динамического удаления или переосмысления графики.
Motion One поддерживает работу с CSS custom properties, что позволяет управлять stroke через переменные.
document.documentElement.style.setProperty("--dash", length)
animate(path, { strokeDashoffset: "var(--dash)" }, { duration: 0 })
Далее анимация может изменять переменную, связывая SVG с глобальным состоянием интерфейса.
Stroke-анимации используются в:
Motion One обеспечивает единый API для всех этих сценариев, позволяя избегать ручной работы с requestAnimationFrame и математикой интерполяции.
Типовые архитектуры stroke-анимаций:
Последовательное появление path без задержек и ветвлений.
Группы path с разными задержками и длительностью.
Прогресс зависит от событий: hover, scroll, pointermove.
Повторяющаяся анимация с reset состояния strokeDashoffset.
animate(
path,
{ strokeDashoffset: length },
{
duration: 2,
repeat: Infinity
}
)
Каждый цикл начинается с полного скрытия контура и повторяет прорисовку заново.