Плавность анимации и интерполяция

В Two.js анимация объектов строится на плавном изменении их свойств во времени. Основными элементами, обеспечивающими динамику, являются движок рендеринга, объекты сцены и метод update, который позволяет изменять свойства объектов на каждом кадре. Two.js работает с двухмерной графикой, где ключевыми атрибутами для анимации являются координаты (x, y), размеры (width, height, radius), цвет и прозрачность (opacity).


Цикл анимации и Two.update()

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

two.play();

Для контроля анимации на каждом кадре добавляется обработчик событий:

two.bind('upd ate', function(frameCount) {
  // изменение свойств объектов
}).play();

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


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

Для плавного перехода одного значения в другое используется линейная интерполяция. Формула:

[ v = v_0 + (v_1 - v_0) t]

где:

  • v0 — начальное значение
  • v1 — конечное значение
  • t — нормализованное время (0–1)

Пример перемещения круга по оси X:

let startX = 50;
let endX = 300;
let duration = 120; // кадры
let frame = 0;

two.bind('update', function() {
  let t = frame / duration;
  circle.translation.x = startX + (endX - startX) * t;
  frame++;
});

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


Нелинейные функции интерполяции (easing)

Easing-функции создают эффекты ускорения и замедления. В Two.js можно использовать сторонние библиотеки, например tween.js, либо реализовать простые функции вручную:

  • easeInQuad (ускорение):
function easeInQuad(t) {
  return t * t;
}
  • easeOutQuad (замедление):
function easeOutQuad(t) {
  return t * (2 - t);
}
  • easeInOutCubic (ускорение и замедление):
function easeInOutCubic(t) {
  return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2;
}

Применение функции:

let t = frame / duration;
let easedT = easeInOutCubic(t);
circle.translation.x = startX + (endX - startX) * easedT;

Использование easing придаёт анимации органичность и визуальную гармонию.


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

Two.js позволяет плавно менять цвет объектов через метод Two.Utils.interpolate или вручную, разбивая цвет на каналы RGBA:

function lerpColor(color1, color2, t) {
  let r = color1.r + (color2.r - color1.r) * t;
  let g = color1.g + (color2.g - color1.g) * t;
  let b = color1.b + (color2.b - color1.b) * t;
  return `rgb(${r},${g},${b})`;
}

Пример:

let colorStart = { r: 255, g: 0, b: 0 }; // красный
let colorEnd = { r: 0, g: 0, b: 255 };   // синий

two.bind('update', function() {
  let t = frame / duration;
  circle.fill = lerpColor(colorStart, colorEnd, t);
  frame++;
});

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


Интерполяция по кривым (Path Animation)

Для сложного движения используют кривые, задаваемые через Two.Path или Two.Anchor. Позиция объекта вычисляется по кривой с параметром t:

let path = two.makeCurve([50,50, 150,200, 300,100], false);
let t = 0;

two.bind('update', function() {
  let point = path.getPointAt(t);
  circle.translation.se t(point.x, point.y);
  t += 0.01;
  if (t > 1) t = 0;
});

Метод getPointAt(t) возвращает координаты на кривой при t от 0 до 1, что обеспечивает плавное движение по сложной траектории.


Комбинирование трансформаций

Плавность анимации усиливается, если одновременно анимировать несколько свойств:

two.bind('update', function() {
  let t = frame / duration;
  let easedT = easeInOutCubic(t);

  circle.translation.x = startX + (endX - startX) * easedT;
  circle.scale = 1 + 0.5 * Math.sin(easedT * Math.PI);
  circle.rotation += 0.05;
});

Такой подход создаёт динамичные и выразительные анимации, где движение, масштаб и вращение синхронизированы по времени.


Интерполяция прозрачности и видимости

Изменение свойства opacity позволяет плавно появляться и исчезать объекты:

circle.opacity = easeInOutQuad(t); // плавное появление

В сочетании с позиционными или цветовыми интерполяциями это создаёт эффект появления, исчезновения или мерцания.


Практические рекомендации

  1. Для стабильной анимации использовать встроенный two.bind('update'), а не setInterval или requestAnimationFrame напрямую.
  2. Интерполяции лучше нормализовать на диапазон 0–1 для упрощения работы с easing-функциями.
  3. Цветовые и прозрачностные переходы должны быть согласованы с движением объектов для гармоничного восприятия.
  4. Для сложных траекторий использовать кривые и точки привязки (Two.Path, Two.Anchor).
  5. Смешение разных типов интерполяции (позиция, цвет, масштаб, вращение) позволяет создавать богатую и живую анимацию, не перегружая код.