Реализация анимации в React Native

в 14:46, , рубрики: animations, react.js, ReactJS, Блог компании OTUS. Онлайн-образование, Программирование

Перевод статьи подготовлен специально для студентов курса «ReactJS/React Native-разработчик».

Реализация анимации в React Native - 1


Трудно себе представить мобильное приложение, в котором нет анимации. В вебе анимации обычно простые, если они есть вообще (максимум – одна страница сменяет другую). Анимации же в мобильных приложениях требуют к себе совсем другого внимания.

У CSS3 есть относительно простой API, который позволяет делать несложные анимации. Но в React Native у вас нет этого инструмента. Да если бы и был, то его было бы недостаточно.

Итак, что вам нужно знать, если вы работаете с React Native и вам нужно реализовать полноценные анимации?

В React Native есть такой инструмент, как Animated, но он выглядит устрашающе… по крайней мере поначалу.

Итак, есть три «группы вещей» или «блока», если хотите, о которых вам нужно знать, чтобы работать с анимацией.

Блок 0: Необходимость перемен

Анимации представляют собой изменение одного состояния на другое:

  • Переход из «скрытого» в «видимое»;
  • Переход от круга к квадрату.

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

  • Должен ли объект появиться с изменением прозрачности или он должен просто «упасть» сверху?
  • Должен ли круг просто превратиться в квадрат, или он должен стать треугольником в середине процесса?

Блок 1: Визуальное состояние, известное как Animated.Value

С логической точки зрения любой компонент может быть либо показан, либо скрыт – это значения «истина» и «ложь», среднего тут не существует. В виде состояния, отображение того, показан ли объект будет либо истинным, либо ложным.

В хорошем пользовательском интерфейсе объекты не скрываются внезапно и также внезапно не появляются. Они проявляются постепенно, помогая пользователю разобраться в интерфейсе.
Таким образом, становится ясно, что визуальное состояние может быть чем-то между истинным состоянием и ложным.

Как же так?
Мы можем ввести еще одну переменную для представления диапазона визуального состояния. Нам нужно, чтобы это было число, поскольку независимо от того, какое мы имеем логическое состояние, числа помогают нам представлять промежуточные значения.

this._shown = new Animated.Value(0);

В то время как логическое состояние может быть двоичным (т.е. либо true, либо false, 1 или 0), визуальное состояние – это число с плавающей точкой.

Блок 2: Переходы, известные как Animated.timing

Скажем, какой-либо компонент скрыт: это значит, что логическое состояние его параметров видимости будет ложным, и визуальное состояние будет также 0.0. Но что происходит, когда мы хотим показать компонент? Логическое состояние должно немедленно стать истинным, тогда как визуальное состояние должно постепенно переходить сначала в 0.1, 0.2, … и наконец полностью в 1.0.

Для этого нам нужен способ сообщить визуальному состоянию переход к 1.0.
И такие способы есть. Вообще-то их даже несколько.
Самый простой способ это в основном:

Animated.timing(this._shown, {
  toValue: 1,
  duration: 300,
}).start();

Здесь, мы говорим Animated изменять _shown до 1.0 в промежутке 300 мс.
Есть и другие переходы, и способы организовать несколько переходов, но сейчас мы вполне можем использовать Animated.timing.

Блок 3: Пиксели, известные как Animated.View и interpolate

Наши переходы _shown между 0.0 и 1.0 ничего не значат, если мы их не можем увидеть. Так как же нам это сделать?

Нам нужно каким-то образом использовать _shown для установки степени прозрачности дочернего компонента.

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

<View style={{ opacity: this.state.shown ? 1 : 0 }}>
  <SomeComponent />
</View>

Мы устанавливаем прозрачность в 0, когда скрываем компонент и в 1, когда показываем.

Можем ли мы использовать имеющееся Animated.Value и _shown, чтобы анимировать переход от 0 к 1?

Анимация стилей

Мы можем использовать любое Animated.Value, когда работаем со стилями.
Нам нужно всего лишь изменить View на Animated.View, и теперь у нас есть следующее:

const opacity = this._shown; // This is an Animated.Value
<Animated.View style={{ opacity: opacity }}>
  <SomeComponent />
</Animated.View>

Разве это не статья про анимации? Почему до сих пор не было картинок?

Реализация анимации в React Native - 2

Еще одна вещь: интерполяция

Это слово звучит страшно, но сама идея довольно проста. Интерполяция позволяет нам сохранить визуальное состояние в рамках 0 и 1, но давать возможность «сопоставления» чему-то еще.

Скажем, вместо того чтобы просто создавать компонент-наследника, мы хотим, чтобы сам наш компонент «выпадал сверху». И мы можем это сделать, поставив скрытый компонент на 40px выше, и анимируем его передвижение к желаемой позиции, во время изменения состояния на видимое.

Мы можем «сопоставить» наши значения от 0 до 1 со значениями от -40 до 0, используя обычный вызов interpolate:

const top = this._shown.interpolate({
  inputRange: [0, 1],
  outputRange: [-40, 0],
});

Это создаст новое Animated.Value, значение которого будет от -40 до 0.
Другими словами, оно будет -40, когда _shown равно 0, -20 – при _shown=0.5 и 0 при _shown равному 1.0.

Реализация анимации в React Native - 3

Темная тайна: с помощью interpolate вы можете также менять значения для цветов и градусов.

Выводы:

  • Визуальное состояние – это числовое значение, оно должно отражать переход от одного стиля к другому.
  • Animated.Value позволяет отражать числовое значение визуального состояния.
  • Animated.timing можно использовать для перехода Animated.Value в другое число.
  • Animated.Value может быть использовано для стилей, при замене View на Animated.View.

Интерполяция позволяет сопоставлять один диапазон Animated.Value другому, например диапазон от 0 до 1 к диапазону от 5 до 25 или даже к диапазону между черным и зеленым.

Источники:

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

Автор: MaxRokatansky

Источник


* - обязательные к заполнению поля