Как работают анимации в React Native?
Анимации в React Native позволяют создавать плавные и визуально привлекательные переходы, движения и эффекты интерфейса. Поддержка анимаций реализована как через встроенные API, так и через сторонние библиотеки. В отличие от веба, где используется CSS-анимация и DOM, в React Native анимации управляются на уровне JS и/или нативного кода.
React Native предоставляет два основных подхода для работы с анимацией:
-
Animated API — встроенное решение в React Native
-
Reanimated — сторонняя библиотека с нативной производительностью
Также существует LayoutAnimation, react-native-animatable, react-native-spring, Lottie и другие, но наиболее широко применяются именно Animated и Reanimated.
1. Animated API (встроенное)
Animated — это основной API React Native для создания декларативных, управляемых JS анимаций. Позволяет анимировать числовые значения (Animated.Value) и применять их к стилям.
Типы анимаций:
-
Animated.timing() — плавная линейная анимация
-
Animated.spring() — физическая анимация с пружинкой
-
Animated.decay() — постепенное замедление
-
Animated.loop() — повторение
-
Animated.parallel(), Animated.sequence(), Animated.stagger() — композиции
Пример:
import { Animated } from 'react-native';
import { useRef, useEffect } from 'react';
function FadeInView() {
const opacity = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(opacity, {
toValue: 1,
duration: 1000,
useNativeDriver: true, // всегда использовать при анимации transform/opacity
}).start();
}, \[\]);
return (
<Animated.View style={{ opacity, width: 100, height: 100, backgroundColor: 'tomato' }} />
);
}
Что можно анимировать с Animated:
-
opacity
-
translateX/Y
-
scale
-
rotate
-
height, width (с осторожностью)
-
Цвет и другие свойства (через interpolate)
interpolate позволяет анимировать диапазоны значений:
const scale = opacity.interpolate({
inputRange: \[0, 1\],
outputRange: \[0.5, 1.5\]
});
2. react-native-reanimated
Reanimated — это продвинутая библиотека для анимаций, разработанная компанией Software Mansion. Главная особенность — выполнение анимационной логики на UI потоке, а не в JS, что исключает лаги, вызванные перегрузкой JavaScript.
Установка (v2+):
npm install react-native-reanimated
Особенности:
-
Все вычисления выполняются на нативном уровне
-
Поддержка Gesture Handler (react-native-gesture-handler)
-
Хуки: useSharedValue, useAnimatedStyle, withTiming, withSpring, withDelay, withRepeat
-
Анимации без тормозов, даже при высокой нагрузке
Пример:
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming
} from 'react-native-reanimated';
function Box() {
const opacity = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value
}));
useEffect(() => {
opacity.value = withTiming(1, { duration: 1000 });
}, \[\]);
return (
<Animated.View style={\[{ width: 100, height: 100, backgroundColor: 'blue' }, animatedStyle\]} />
);
}
Преимущества Reanimated:
-
Нет лагов даже на слабых устройствах
-
Сложные анимации (например, физика) работают нативно
-
Комбинация с жестами и GestureDetector
-
Полноценный движок: interpolate, runOnUI, scrollHandler, measure, layout animations
3. LayoutAnimation
LayoutAnimation позволяет анимировать изменения размеров/позиции компонентов при их добавлении/удалении из дерева. Работает нативно, но ограниченно.
Пример:
import { LayoutAnimation, UIManager, Platform } from 'react-native';
if (Platform.OS === 'android') {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
function MyComponent() {
const \[visible, setVisible\] = useState(false);
const toggle = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
setVisible(!visible);
};
return (
<>
<Button onPress={toggle} title="Toggle" />
{visible && <View style={{ height: 100, backgroundColor: 'red' }} />}
</>
);
}
4. Сравнение Animated и Reanimated
Характеристика | Animated | Reanimated |
---|---|---|
Поток выполнения | JS-поток | UI-поток (нативный) |
--- | --- | --- |
Производительность | Зависит от загрузки JS | Высокая, вне зависимости от JS |
--- | --- | --- |
Поддержка жестов | Ограниченная | Полная (в связке с Gesture Handler) |
--- | --- | --- |
API | Простое, декларативное | Сложнее, но гибче |
--- | --- | --- |
Подходит для | Простых анимаций (opacity, scale) | Сложных взаимодействий и UI анимаций |
--- | --- | --- |
Поддержка хуков | useRef + Animated.Value | useSharedValue, useAnimatedStyle |
--- | --- | --- |
Частые сценарии использования анимаций
-
Появление/исчезновение элементов
-
Плавные переходы между экранами
-
Анимированные списки, карусели, табы
-
Жесты drag'n'drop
-
Прогресс-бары и индикаторы
-
Анимации состояний (включено/выключено, ошибки и т.п.)
Советы по производительности
-
Всегда использовать useNativeDriver: true в Animated
-
Для сложных сценариев использовать Reanimated
-
Комбинировать с react-native-gesture-handler для UI интерактивности
-
Не анимировать layout-свойства напрямую (например, margin, padding) — используйте transform
-
Использовать interpolate() вместо нескольких Animated.Value
Анимации в React Native строятся либо через декларативный подход (Animated), либо через нативную оптимизированную модель (Reanimated). Выбор зависит от требований к производительности и сложности интерфейса. Простые эффекты легко реализовать с Animated, а интерактивные, жесткозависимые и высокопроизводительные — с Reanimated.