Линейная интерполяция

Линейная интерполяция является базовым механизмом построения анимаций в mo.js и в большинстве современных систем визуальных эффектов. Она определяет способ вычисления промежуточных значений между двумя состояниями, обеспечивая плавный переход параметров объекта во времени.

Линейная интерполяция (LERP) задаётся формулой:

[ LERP(a, b, t) = a + (b - a) t]

где:

  • a — начальное значение,
  • b — конечное значение,
  • t — коэффициент интерполяции в диапазоне от 0 до 1.

При t = 0 результат равен начальному значению, при t = 1 — конечному. Все промежуточные значения формируют прямую траекторию перехода без ускорений и замедлений.

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

Интерпретация времени в анимационных системах

В системах анимации значение t не задаётся напрямую, а вычисляется из текущего времени:

  • фиксируется старт анимации,
  • определяется длительность,
  • вычисляется прошедшее время,
  • нормализуется в диапазон [0..1].

Формально:

[ t = ]

При превышении длительности t ограничивается значением 1.

Роль линейной интерполяции в mo.js

В mo.js линейная интерполяция используется как базовый механизм изменения свойств объектов Tween, Shape, Burst и других анимационных сущностей. Несмотря на наличие easing-функций, именно LERP остаётся фундаментом, на котором строится любое изменение параметров.

Любое анимируемое свойство в mo.js можно представить как интерполяцию между двумя состояниями:

  • координаты (x, y),
  • масштаб (scale),
  • поворот (angle),
  • прозрачность (opacity),
  • параметры формы и деформации.

Простейшая реализация LERP в JavaScript

function lerp(a, b, t) {
  return a + (b - a) * t;
}

Применение:

const start = 0;
const end = 200;

const value = lerp(start, end, 0.5); // 100

В анимации это значение обновляется на каждом кадре.

Линейная интерполяция в tween-анимациях

В mo.js основной строительный блок анимации — Tween. Он описывает переход свойств объекта во времени.

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

const tween = new mojs.Tween({
  duration: 1000,
  onUpdate(progress) {
    const x = lerp(0, 300, progress);
    element.style.transform = `translateX(${x}px)`;
  }
});

Здесь progress — это нормализованное значение t, вычисляемое движком.

Свойства и их интерполяция

Линейная интерполяция применяется ко всем числовым параметрам. Для каждого свойства создаётся независимая функция LERP.

Позиция

x = lerp(x1, x2, t);
y = lerp(y1, y2, t);

Масштаб

scale = lerp(1, 2, t);

Прозрачность

opacity = lerp(1, 0, t);

Плавное исчезновение достигается прямой интерполяцией без дополнительных вычислений.

Векторная интерполяция

Для объектов с несколькими измерениями используется покомпонентная интерполяция:

function lerpVec2(a, b, t) {
  return {
    x: a.x + (b.x - a.x) * t,
    y: a.y + (b.y - a.y) * t
  };
}

mo.js использует аналогичный подход для координат и трансформаций объектов.

Отличие линейной интерполяции от easing-функций

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

Easing-функции преобразуют t:

t' = ease(t)

и уже затем применяется LERP:

value = lerp(a, b, t')

Таким образом, линейная интерполяция остаётся базовым слоем, а easing — надстройкой над ней.

Использование интерполяции в requestAnimationFrame

Низкоуровневая реализация анимации сводится к циклу:

let start = null;

function animate(timestamp) {
  if (!start) start = timestamp;

  const time = timestamp - start;
  let t = time / 1000;

  if (t > 1) t = 1;

  const x = lerp(0, 500, t);
  element.style.transform = `translateX(${x}px)`;

  if (t < 1) {
    requestAnimationFrame(animate);
  }
}

requestAnimationFrame(animate);

mo.js автоматизирует эту модель, скрывая вычисление t и управление кадрами.

Интерполяция в timeline-структурах

В сложных сценах mo.js использует последовательности анимаций, где каждая часть имеет собственный диапазон времени.

Если существует timeline с двумя последовательными tween:

  • первый: t ∈ [0..0.5]
  • второй: t ∈ [0.5..1]

то интерполяция выполняется локально внутри каждого сегмента:

t_local = (t - t_start) / (t_end - t_start);

Каждый сегмент применяет собственный LERP.

Интерполяция в параметрических формах

В анимациях форм (shape animations) интерполяция применяется не только к позициям, но и к геометрии.

Пример изменения радиуса:

radius = lerp(10, 80, t);

или изменения количества элементов:

count = Math.round(lerp(3, 12, t));

Для burst-анимаций это особенно важно, так как создаётся эффект расширения или распада.

Нестандартные применения линейной интерполяции

Помимо стандартных числовых значений, LERP используется для:

  • смешивания цветов (RGB интерполяция),
  • изменения толщины линий,
  • контроля задержек между событиями,
  • управления случайностью через seed-интерполяцию.

Интерполяция цвета:

function lerpColor(c1, c2, t) {
  return {
    r: lerp(c1.r, c2.r, t),
    g: lerp(c1.g, c2.g, t),
    b: lerp(c1.b, c2.b, t)
  };
}

Ограничения линейной интерполяции

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

  • постоянная скорость изменения,
  • отсутствие физической динамики,
  • визуальная «жёсткость» переходов,
  • невозможность имитации инерции.

По этой причине она почти всегда комбинируется с нелинейными функциями.

Комбинирование нескольких интерполяций

В сложных анимациях применяется вложенная интерполяция:

value = lerp(a, b, ease(lerp(0, 1, t)));

или обратная схема:

value = ease(lerp(a, b, t));

В зависимости от архитектуры системы mo.js может применять обе модели в разных слоях.

Интерполяция и производительность

Линейная интерполяция является одной из самых дешёвых операций:

  • одна операция вычитания,
  • одна операция умножения,
  • одно сложение.

Это делает её оптимальной для массовых анимаций, особенно в burst-сценах, где одновременно обновляются сотни объектов.

Переход между состояниями как основа motion design

Любая анимация в mo.js сводится к набору интерполяций:

  • состояние A → состояние B,
  • набор числовых свойств,
  • временная функция t.

Даже сложные визуальные эффекты представляют собой композицию простых LERP-операций, синхронизированных по времени и сгруппированных в структуры tween и timeline.