Linear и stepped

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

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

Принцип работы

Пусть задан входной диапазон [inputMin, inputMax] и соответствующий выходной диапазон [outputMin, outputMax]. Тогда для любого значения v внутри входного диапазона вычисляется соответствующее значение в выходном диапазоне.

Popmotion предоставляет функцию interpolate, реализующую этот механизм:

import { interpolate } from "popmotion";

const transformer = interpolate(
  [0, 100],    // входной диапазон
  [0, 1]       // выходной диапазон
);

transformer(50); // 0.5

Множественные сегменты

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

const transformer = interpolate(
  [0, 50, 100],
  [0, 200, 300]
);

transformer(25);  // 100
transformer(75);  // 250

Каждый сегмент интерполируется независимо, но результат остаётся непрерывным.

Экстраполяция

По умолчанию значения, выходящие за пределы диапазона, продолжают интерполяцию. Это поведение можно изменить:

const transformer = interpolate(
  [0, 100],
  [0, 1],
  { clamp: true }
);

transformer(150); // 1

Параметр clamp ограничивает результат границами выходного диапазона.

Использование easing-функций

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

import { easeIn } from "popmotion";

const transformer = interpolate(
  [0, 100],
  [0, 1],
  { ease: easeIn }
);

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


Ступенчатая интерполяция (Stepped)

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

Принцип работы

Значения входного диапазона разбиваются на интервалы, каждому из которых соответствует фиксированное значение.

import { interpolate } from "popmotion";

const transformer = interpolate(
  [0, 50, 100],
  [0, 1, 2],
  { ease: "steps(2)" }
);

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

Использование steps

import { steps } from "popmotion";

const stepped = steps(5);

stepped(0.1); // 0
stepped(0.5); // 0.5
stepped(0.9); // 0.8

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

Связка с interpolate

Ступенчатое поведение часто комбинируется с интерполяцией:

import { interpolate, steps } from "popmotion";

const transformer = interpolate(
  [0, 100],
  [0, 1],
  {
    ease: steps(4)
  }
);

transformer(25); // 0.25
transformer(30); // 0.25

Значение изменяется только при переходе между шагами.


Отличия Linear и Stepped

Характеристика Linear Stepped
Тип перехода Плавный Дискретный
Промежуточные значения Есть Отсутствуют
Использование Анимации, скролл, UI Тайминги, переключатели
Поведение Непрерывное Скачкообразное

Практические сценарии

Линейное преобразование скролла

const opacity = interpolate(
  [0, 300],
  [0, 1]
);

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

Ступенчатый прогресс-бар

const progress = interpolate(
  [0, 100],
  [0, 1],
  { ease: steps(10) }
);

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

Переключение состояний

const state = interpolate(
  [0, 1],
  ["off", "on"],
  { ease: steps(1) }
);

Реализует бинарное переключение без промежуточных значений.


Особенности реализации в Popmotion

  • Интерполяция реализована как чистая функция без побочных эффектов
  • Поддерживается работа с числами, цветами, строками и комплексными значениями
  • Возможна композиция трансформеров
  • Высокая производительность за счёт отсутствия лишних вычислений

Композиция трансформеров

import { pipe, interpolate, steps } from "popmotion";

const transformer = pipe(
  interpolate([0, 100], [0, 1]),
  steps(5)
);

Позволяет комбинировать линейную и ступенчатую логику.


Работа с цветами

Линейная интерполяция поддерживает цвета:

const color = interpolate(
  [0, 100],
  ["#ff0000", "#00ff00"]
);

color(50); // промежуточный цвет

Ступенчатый вариант:

const color = interpolate(
  [0, 100],
  ["#ff0000", "#00ff00"],
  { ease: steps(1) }
);

Результат будет либо полностью красным, либо зелёным.


Контроль точности

При линейной интерполяции важно учитывать:

  • плавающую точку
  • накопление ошибок
  • ограничения диапазона

Ступенчатая интерполяция избавляет от этих проблем, но жертвует плавностью.


Влияние на UX

  • Linear создаёт ощущение естественного движения
  • Stepped подчёркивает дискретность и логические состояния

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