Гид по технологиям

Создание непрерывных анимаций в React Native с Animated.loop()

5 min read Development Обновлено 26 Dec 2025
Animated.loop в React Native: непрерывные анимации
Animated.loop в React Native: непрерывные анимации

Человек за MacBook во время разработки бэкенда

Зачем нужен Animated.loop

Animated.loop() — это удобный способ сделать анимацию цикличной. Основная идея: создаётся Animated.Value, который меняет своё значение на каждом кадре анимации, а Animated.loop() повторяет указанную анимацию столько раз, сколько нужно (или бесконечно по умолчанию). Это полезно для индикаторов загрузки, вращающихся иконок, циклических переходов и фоновых эффектов.

Термин в одну строку:

  • Animated.Value — числовой контейнер, который обновляется анимацией.
  • Animated.timing — тайминговая анимация, изменяет значение с течением времени.
  • useNativeDriver — флаг, который выполняет анимацию на нативной стороне для лучшей производительности (не поддерживает все свойства).

Базовое использование Animated.loop

Шаги:

  1. Создайте Animated.Value.
  2. Опишите анимацию (например, Animated.timing).
  3. Оберните анимацию в Animated.loop({ iterations: N }).
  4. Запустите .start().

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

import React, { useEffect, useRef } from 'react';
import { StyleSheet, View, Animated, Image } from 'react-native';

export default function App() {
  const spinValue = useRef(new Animated.Value(0)).current;

  useEffect(() => {
    const spin = spinValue.interpolate({
      inputRange: [0, 1],
      outputRange: ['0deg', '360deg'],
    });

    const timing = Animated.timing(spinValue, {
      toValue: 1,
      duration: 2000, // 2000 ms = 2 с
      useNativeDriver: true,
      isInteraction: false,
    });

    Animated.loop(timing).start();

    // Опционально: очистка при размонтировании
    return () => spinValue.stopAnimation();
  }, [spinValue]);

  const spin = spinValue.interpolate({
    inputRange: [0, 1],
    outputRange: ['0deg', '360deg'],
  });

  return (
    
      
    
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

Важно: в transform используйте интерполированное значение (spin), а не сам Animated.Value напрямую. В примере duration указано как 2000 ms (2 с).

Управление количеством повторов и остановка

  • По умолчанию Animated.loop() создаёт бесконечный цикл.
  • Чтобы задать фиксированное число повторов, передайте параметр iterations: Animated.loop(timing, { iterations: 5 }).
  • Для остановки — сохраните ссылку на анимацию и вызовите .stop(), либо используйте условие в useEffect, которое снимает слушатели и вызывает stopAnimation на Animated.Value.

Пример с ограниченным числом итераций:

Animated.loop(timing, { iterations: 5 }).start(() => {
  // колбэк после завершения всех итераций
});

Работа с комплексными анимациями

Сложные сценки обычно состоят из нескольких независимых анимаций (положение, вращение, прозрачность). Рекомендации:

  1. Разбивайте анимацию на этапы
  • Легче отлаживать и комбинировать.
  • Можно параллельно или последовательно объединять их в Animated.parallel или Animated.sequence.
  1. Используйте Animated.sequence для последовательности
  • Animated.sequence([anim1, anim2, anim3]) выполняет набор анимаций одна за другой.
  • Оберните sequence в Animated.loop, чтобы повторять всю последовательность.

Пример: показать → повернуть → скрыть (зациклено)

const sequence = Animated.sequence([
  Animated.timing(opacityValue, { toValue: 1, duration: 400, useNativeDriver: true }),
  Animated.timing(spinValue, { toValue: 1, duration: 1200, useNativeDriver: true }),
  Animated.timing(opacityValue, { toValue: 0, duration: 400, useNativeDriver: true }),
]);

Animated.loop(sequence).start();

Когда Animated.loop может не подойти

  • Нужна точная физическая симуляция (меньше контроля над фреймами): лучше Reanimated 2 или физические движки.
  • Нужно анимировать layout-свойства (width/height/margin) с useNativeDriver — это не поддерживается. Для таких свойств используйте LayoutAnimation или анимируйте трансформации вместо размеров.
  • Сложные последовательности с условной логикой — удобнее реализовать с управлением состояния и явными таймерами.

Альтернативные подходы

  • Reanimated 2/3: больше возможностей, работа на нативной стороне и поддержка сложных вычислений без мостов.
  • Lottie: для векторных сложных анимаций, импортированных из Adobe After Effects.
  • react-native-animatable: быстрые примитивы для простых UI-анимаций.

Производительность и useNativeDriver

useNativeDriver: true переносит анимацию в нативную очередь рендеринга, что снижает задержки и джиттер. Однако нативный драйвер не поддерживает все CSS-подобные свойства (например, width или backgroundColor не всегда поддерживаются). Правило:

  • Анимируйте transform и opacity через useNativeDriver.
  • Для остальных свойств ищите обходы (scale вместо width, маскировка) или используйте JS-driven анимации для свойств, которые нужно менять через JS.

Important: если вы видите «Property XYZ is not supported by native animated module», замените свойство или снимите useNativeDriver и измерьте влияние на производительность.

Проверка и критерии приёмки

Критерии приёмки:

  • Анимация запускается и визуально плавная на тестовых устройствах (iOS и Android).
  • При заданных iterations анимация остановлена после нужного числа циклов.
  • При размонтировании компонента анимация не вызывает утечек памяти (stopAnimation вызывается).
  • Использование useNativeDriver не ломает желаемые свойства.

Тесты/acceptance:

  • Функциональный: логотип вращается без рывков при 60 FPS (проверка на реальном устройстве).
  • Стабильность: старт/стоп анимации 50 раз подряд без падений.
  • Ресурсы: мониторинг CPU/GPU при работе анимации, отсутствие значительного перегрева на старых устройствах.

Роль‑ориентированные чек-листы

Разработчик:

  • Разбил сложную анимацию на мелкие шаги.
  • Проверил useNativeDriver и поддержку свойств.
  • Добавил очистку анимации в unmount.

Дизайнер:

  • Предоставил референс анимации (видео или прототип).
  • Уточнил длительности, easing и поведение в разных состояниях.

QA:

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

Модель принятия решений (набросок)

  • Нужна ли нативная производительность? -> Да: useNativeDriver / Reanimated.
  • Требуется ли анимация layout? -> Да: LayoutAnimation или JS-driven.
  • Сложная последовательность/физика? -> Reanimated или физические движки.

Советы по отладке

  • Логи: spinValue.addListener(value => console.log(value));
  • Проверяйте, что interpolate возвращает строку с ‘deg’ для rotate.
  • Убедитесь, что Animated.Value сбрасывается/реинициализируется при необходимости.

Факт-бокс — ключевые числа

  • duration: часто 2000 ms (2 с) для одного оборота.
  • iterations: по умолчанию бесконечно (omit для бесконечного цикла).
  • useNativeDriver: рекомендуется для transform и opacity.

Совместимость и миграция

  • Animated API стабилен в React Native, но для высоконагруженных и сложных анимаций рассмотрите Reanimated v2/v3.
  • При миграции с Animated на Reanimated потребуется переписать логику анимаций и интерполяций на хуки Reanimated.

Короткие рекомендации по безопасности и приватности

Анимации не отправляют данные пользователей и не влияют на приватность напрямую. Обратите внимание на вычисления в реальном времени: избегайте логирования чувствительных данных внутри listeners.

Заключение

Animated.loop — простой и эффективный инструмент для создания зацикленных анимаций в React Native. Разбивайте сложные эффекты на части, используйте Animated.sequence/parallel, и подключайте useNativeDriver для оптимальной производительности. Для очень сложных и производительных задач рассмотрите Reanimated.

Ключевые выводы:

  • Animated.loop удобно зацикливать простые и составные анимации.
  • Используйте интерполяцию при работе с rotate и другими преобразованиями.
  • Разбивайте сложные сценарии и тестируйте на реальных устройствах.
Поделиться: X/Twitter Facebook LinkedIn Telegram
Автор
Редакция

Похожие материалы

Как смотреть видео в VR: Oculus, Rift, Vive, Gear, Daydream
VR

Как смотреть видео в VR: Oculus, Rift, Vive, Gear, Daydream

Как сохранить изображения из Google Images
Инструкции

Как сохранить изображения из Google Images

Фокус-стекинг вручную в Photoshop
Фотография

Фокус-стекинг вручную в Photoshop

Как исправить синхронизацию iPod с компьютером
Техподдержка

Как исправить синхронизацию iPod с компьютером

Длительная выдержка на Samsung Galaxy
Фотография

Длительная выдержка на Samsung Galaxy

Как подключить Bluetooth наушники к HDTV
Руководство

Как подключить Bluetooth наушники к HDTV