Кастомные функции времени

Роль временной функции в механике отрисовки

В анимациях SVG, основанных на поэтапном раскрытии контуров, ключевым элементом управления становится преобразование линейного времени в нелинейный прогресс. Базовая модель предполагает нормализацию времени в диапазон [0; 1], где 0 соответствует началу анимации, а 1 — её завершению.

Линейная зависимость задаётся тривиально:

f(t) = t

Однако визуальное восприятие движения почти всегда требует иного характера изменения скорости: ускорения, замедления, инерции, «пружинного» эффекта. Именно это и формируют кастомные функции времени.

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


Базовая модель интерполяции в SVG-анимации

Любая анимация построена на изменении параметра обводки:

  • stroke-dasharray задаёт структуру штриха
  • stroke-dashoffset управляет видимой частью линии

Функционально это сводится к вычислению коэффициента заполнения пути:

p(t)

где p(t) — прогресс отрисовки.

При линейной функции:

p(t) = t

при кастомной:

p(t) = f(t)

Функция f(t) определяет характер движения по контуру SVG.


Архитектура временных функций в Vivus

Внутренняя логика анимации в Vivus строится вокруг цикла обновления кадра:

  1. фиксируется стартовое время
  2. вычисляется прошедшее время
  3. нормализуется в диапазон [0;1]
  4. применяется временная функция
  5. результат используется для расчёта обводки

Схематически:

t =

strokeOffset = length (1 - p)

Таким образом, функция времени напрямую определяет скорость визуального «прорисовывания» SVG-пути.


Типы кастомных функций времени

Линейная функция

Самый простой вариант, обеспечивающий равномерную скорость:

f(t) = t

Поведение полностью предсказуемо, но визуально часто воспринимается как механическое.


Квадратическое ускорение

Создаёт эффект плавного разгона:

f(t) = t^2

В начале движение почти незаметно, затем интенсивность резко возрастает.


Замедление к концу

Инвертированная квадратичная функция:

f(t) = 1 - (1 - t)^2

Используется для эффектов «доделывания» линии, когда основной объём отрисовки происходит быстро, а финал — плавный.


Кубические и более сложные кривые

Более гибкое управление даёт кубическая интерполяция:

f(t) = t^3

или комбинации:

f(t) = 3t^2 - 2t^3

Такая форма часто используется как базовая easing-функция без резких скачков производной.


Подключение кастомной функции времени в Vivus

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

Типовая структура:

new Vivus('my-svg', {
  duration: 200,
  animTimingFunction: function (t) {
    return t;
  }
});

Функция вызывается на каждом кадре, где t ∈ [0;1].


Дискретизация и влияние частоты кадров

Поскольку анимация выполняется через requestAnimationFrame, фактический прогресс дискретизируется:

t_n = f()

где:

  • n — текущий кадр
  • N — общее число кадров

Чем более резкая функция f(t), тем сильнее визуально заметны скачки при низкой частоте кадров.


Ограничение значений функции времени

Корректная временная функция должна сохранять область значений:

f(t) t

При выходе за границы возникают артефакты:

  • отрицательные значения приводят к «обратной» отрисовке
  • значения больше 1 вызывают переразрисовку и визуальные скачки

Обычно применяется нормализация:

f_{norm}(t) = (1, (0, f(t)))


Комбинированные функции времени

Более сложные эффекты достигаются через композицию:

f(t) = a f_1(t) + (1 - a) f_2(t)

где a управляет вкладом каждой функции.

Пример гибридной модели:

  • ускорение в начале
  • замедление в конце

f(t) = 3t^2 - 2t^3

Такая форма часто используется как универсальная easing-кривая.


Применение к SVG-пути

Внутренне SVG-путь разбивается на сегменты, и прогресс функции времени распределяется по длине:

L_{drawn} = L_{total} f(t)

где:

  • L_total — полная длина пути
  • L_drawn — текущая длина отображаемой части

Это преобразуется в stroke-dashoffset, который визуально «скрывает» или «раскрывает» линию.


Практические стратегии построения функций

Плавное появление с инерцией

Функция с медленным стартом и ускорением:

f(t) = t^2(3 - 2t)

Резкий старт и плавное завершение

f(t) =

Эффект «дыхания» в анимации

f(t) = t + 0.05(2t)

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


Производительность вычислений временных функций

В контексте SVG-анимаций вычисление функции времени выполняется на каждом кадре, что накладывает ограничения:

  • функция должна быть вычислительно дешёвой
  • избегаются тригонометрические выражения высокой сложности
  • предпочтительны полиномиальные формы

Сложные функции приводят к росту нагрузки на главный поток браузера, особенно при большом количестве одновременно анимируемых SVG-элементов.


Связь временной функции с восприятием формы

Одна и та же геометрия SVG может восприниматься по-разному в зависимости от временной функции:

  • линейная функция подчёркивает структуру пути
  • ускоряющая функция акцентирует финальные элементы
  • замедляющая функция делает акцент на начале композиции

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