Руководства · 01

Значения и стили

Владейте значением в компоненте, выводите результаты через calc() и выбирайте, куда записывается CSS-переменная.

Владение значением

useAnimatedValue(initial) создаёт Value, принадлежащее компоненту. Используйте число или запись вроде { x: 0, opacity: 1 }, поля которой — отдельные значения.

В обычном style значение хука — это токен var(--kkwa-…, initial). Обновления записывают эту переменную в элементы, которые её используют; React не перерисовывает.

Подготовка примера…

Вывод через calc()

Интерполяция без easing и add, subtract, multiply или divide на константу становятся точными выражениями calc() той же переменной. Их вычисляет браузер; JavaScript для них на каждом кадре не выполняется.

Slide.jsx
const progress = useAnimatedValue(0);

// A linear interpolation of a hook value is a calc() of the same CSS variable.
const x = progress.interpolate({ inputRange: [0, 1], outputRange: ['0px', '180px'] });
const half = multiply(progress, 0.5);

<div style={{ opacity: half, transform: `translateX(${x})` }} />;

Подготовка примера…

Цвета и собственные вычисления

Цвета, интерполяции с easing, modulo, diffClamp и AnimatedComputed нельзя записать как calc(). useAnimatedCSS(node) даёт им собственную CSS-переменную, которую обновляет JavaScript, с тем же временем жизни компонента.

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

Glow.jsx
const progress = useAnimatedValue(0);

// Colors and eased curves are not calc() expressions: give them their own CSS value.
const color = useAnimatedCSS(
  progress.interpolate({ inputRange: [0, 1], outputRange: ['#3d3bf3', '#22b8f0'] }),
);

<div style={{ background: color }} />;

Пусть хук владеет рецептом

useAnimated(initial, factory, deps) владеет значением и каждым контроллером, синхронно объявленным в фабрике. Запускается при монтировании, перезапускается при изменении зависимости и останавливается при размонтировании.

Передайте { autoStart: false } для воспроизведения по событиям, затем вызывайте start(), stop() или reset() у возвращённого значения.

Intro.jsx
const intro = useAnimated(
  { opacity: 0, y: 24 },
  (value) => {
    parallel([
      timing(value.opacity, { toValue: 1, duration: 400 }),
      spring(value.y, { toValue: 0, stiffness: 220, damping: 20 }),
    ]);
  },
  [],
);

<section style={{ opacity: intro.opacity, transform: `translateY(calc(${intro.y} * 1px))` }} />;

Одна запись для многих элементов

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

AnimatedProvider scope={ref} задаёт область по умолчанию для всех значений хуков внутри него.

Field.jsx
const field = useRef(null);

// Written once on the field; every child that uses the value inherits it.
const wave = useAnimatedValue(0, { scope: field });

<div ref={field}>
  {items.map((item) => (
    <i key={item} style={{ transform: `rotate(calc(${wave} * 1turn))` }} />
  ))}
</div>;

Чтение значений в JavaScript

getValue() возвращает снимок без подписки React. useAnimatedListener(node, fn) вызывает вас при каждом изменении и удаляет слушателя при размонтировании. Используйте его для рисования на canvas или аналитики, а не для рендеринга.

Поиск

Начните вводить, чтобы искать в документации.