Анимация одного свойства

В Motion One анимация строится вокруг изменения отдельных CSS-свойств во времени. Основная идея заключается в том, что вместо сложных конфигураций и громоздких API разработчик задаёт минимальный набор параметров: элемент, свойство и конечное значение. Библиотека берёт на себя вычисление промежуточных кадров, интерполяцию значений и управление временем.

Анимация одного свойства — это фундаментальная операция, на которой строятся более сложные эффекты. Именно она позволяет понять поведение Motion One на базовом уровне: как изменяются стили, как работает синхронизация времени и каким образом формируются переходы.


Функция animate и её базовая структура

Основной инструмент работы — функция animate.

Структура вызова:

import { animate } from "motion";

animate(
  элемент,
  { свойство: конечноеЗначение },
  параметрыАнимации
);

Минимальный вариант:

animate(
  ".box",
  { opacity: 1 }
);

В этом случае:

  • .box — целевой элемент
  • opacity: 1 — конечное значение свойства
  • параметры анимации используются по умолчанию

Если элемент уже имеет другое значение opacity, библиотека автоматически определяет стартовое состояние и выполняет плавный переход.


Анимация прозрачности

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

animate(
  ".box",
  { opacity: 0 }
);

Поведение:

  • текущее значение opacity считывается из computed styles
  • происходит интерполяция от текущего значения к 0
  • итоговое состояние фиксируется в DOM

Анимация может быть инвертирована:

animate(
  ".box",
  { opacity: 1 }
);

Особенности интерполяции opacity

  • диапазон значений строго числовой (0–1)
  • промежуточные значения вычисляются линейно или через easing
  • не требует преобразования единиц измерения

Анимация размеров через width и height

Motion One поддерживает свойства с единицами измерения. Например, px, %, em.

animate(
  ".box",
  { width: "300px" }
);

Переход может происходить от любого исходного значения:

animate(
  ".box",
  { width: "50%" }
);

Внутренний механизм

При анимации размеров происходит:

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

Таким образом:

100px → 300px

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

100px → 140px → 190px → 240px → 300px

Цветовые свойства

Motion One поддерживает анимацию цвета в различных форматах:

  • hex (#ff0000)
  • rgb (rgb(255, 0, 0))
  • rgba (rgba(255, 0, 0, 1))

Пример:

animate(
  ".box",
  { backgroundColor: "#ff0000" }
);

Внутреннее преобразование цвета

Библиотека:

  • нормализует формат цвета
  • преобразует значение в RGBA
  • интерполирует каждый канал отдельно

Пример перехода:

rgb(0, 0, 0) → rgb(255, 0, 0)

Результирующая интерполяция:

  • R увеличивается от 0 до 255
  • G остаётся 0
  • B остаётся 0
  • A сохраняется или изменяется отдельно

Позиционирование через transform

Одним из наиболее производительных способов анимации является использование transform. В отличие от layout-свойств, transform не вызывает перерасчёт макета страницы.

Перемещение по оси X

animate(
  ".box",
  { x: 200 }
);

В Motion One свойство x является сокращением для:

transform: translateX(...)

Перемещение по оси Y

animate(
  ".box",
  { y: 150 }
);

Интерполяция числовых значений

Основной механизм Motion One основан на числовой интерполяции.

Формула:

value = start + (end - start) * progress

Где:

  • start — начальное значение
  • end — конечное значение
  • progress — прогресс анимации (0 → 1)

Пример:

start = 0
end = 100
progress = 0.5

value = 0 + (100 - 0) * 0.5 = 50

Управление длительностью анимации

Параметр duration задаёт время выполнения анимации в миллисекундах.

animate(
  ".box",
  { opacity: 0 },
  { duration: 1000 }
);

Поведение длительности

  • 1000 ms = 1 секунда
  • увеличение duration замедляет интерполяцию
  • уменьшение duration ускоряет переход

Easing и характер движения

Easing определяет кривую изменения прогресса анимации.

Пример:

animate(
  ".box",
  { x: 300 },
  { easing: "ease-in-out" }
);

Влияние easing

Без easing (линейная интерполяция):

progress = t

С easing:

progress = f(t)

Где f(t) — функция кривой, изменяющая скорость движения.


Анимация от текущего состояния

Motion One автоматически определяет стартовое значение свойства.

animate(
  ".box",
  { opacity: 0 }
);

Если элемент уже имеет:

opacity: 0.8;

то интерполяция будет:

0.8 → 0

При этом разработчик не обязан явно указывать начальное значение.


Перезапуск анимации одного свойства

При повторном вызове animate для одного и того же свойства происходит:

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

Пример:

animate(".box", { x: 100 });
animate(".box", { x: 300 });

Фактически первая анимация прерывается и заменяется новой.


Относительные значения

Motion One поддерживает относительные изменения:

animate(
  ".box",
  { x: "+=100" }
);

Поведение:

  • текущее значение считывается
  • к нему добавляется указанная величина
  • формируется новое конечное значение

Если текущее x = 200, то:

200 + 100 = 300

Отрицательные значения и обратные переходы

Анимация может двигаться в обратном направлении:

animate(
  ".box",
  { x: -200 }
);

Также возможны переходы через ноль:

150 → -150

Интерполяция при этом остаётся линейной по числовой оси.


Смешанные единицы измерения

Motion One способен интерполировать значения с одинаковыми единицами:

animate(
  ".box",
  { width: "50vw" }
);

Если стартовое значение также в vw, происходит прямое числовое сравнение.

При несовпадении единиц:

  • выполняется преобразование в пиксели
  • затем интерполяция
  • затем обратное преобразование при необходимости

Ограничения анимации одного свойства

При всей универсальности существуют ограничения:

  • нельзя смешивать несовместимые типы (например, число и сложный CSS-градиент без преобразования)
  • некоторые свойства требуют layout recalculation
  • часть свойств анимируется через transform для оптимизации

Производительность при анимации одного свойства

Анимация одного свойства является наиболее дешёвым сценарием для браузера при правильном выборе свойства.

Наиболее оптимальные:

  • transform
  • opacity

Менее оптимальные:

  • width
  • height
  • top / left

Причина:

  • layout properties вызывают перерасчёт геометрии
  • transform работает на уровне compositor thread

Поведение при отсутствии начального значения

Если свойство не задано в CSS, Motion One:

  • считывает computed style
  • при невозможности — использует дефолтное значение браузера
  • начинает интерполяцию от этого значения

Пример:

animate(".box", { opacity: 1 });

Если opacity не задан:

opacity = 1 (default)

Каскад и переопределение стилей

Во время анимации Motion One:

  • временно управляет inline-стилями
  • переопределяет CSS каскад для анимируемого свойства
  • сохраняет итоговое значение после завершения

Это обеспечивает предсказуемость результата независимо от внешних стилей.


Синхронность анимаций одного свойства

Несколько анимаций одного свойства на разных элементах выполняются независимо:

animate(".box1", { x: 100 });
animate(".box2", { x: 200 });

Каждый элемент получает собственный timeline и интерполяцию.


Поведение при резком изменении состояния

Если во время анимации меняется DOM или стиль:

  • Motion One пересчитывает текущую позицию
  • новая анимация начинается от актуального значения
  • визуальный разрыв минимизируется за счёт мгновенной синхронизации состояния