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

Бесконечные анимации в React Native с Animated.loop

5 min read React Native Обновлено 28 Mar 2026
Animated.loop в React Native — зацикленные анимации
Animated.loop в React Native — зацикленные анимации

Человек использует MacBook для разработки бэкенда

Animated.loop — один из ключевых инструментов Animated API в React Native для создания повторяющихся анимаций. В этой статье мы подробно разберём, как его применять, как настраивать поведение цикла, какие ограничения учитывать и какие альтернативы использовать для сложных или производительных задач.

Что такое Animated.loop

Animated.loop — это обёртка над любой анимацией Animated (например, Animated.timing, Animated.spring, Animated.sequence), которая повторяет вложенную анимацию заданное количество раз или бесконечно по умолчанию.

Кратко:

  • Animated.Value — примитив состояния анимации. Обновляется по кадрам.
  • Animated.timing/Animated.spring задают траекторию изменения значения.
  • Animated.loop повторяет переданную анимацию.

Важно: Animated.loop сам по себе не создаёт нового Animated.Value — он повторно использует существующую анимацию и её конфигурацию.

Простой пример: вечное вращение

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

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

export default function App() {
  const [spinValue] = useState(new Animated.Value(0));

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

    Animated.loop(
      Animated.timing(
        spinValue,
        {
          toValue: 1,
          duration: 2000,
          useNativeDriver: true,
        }
      )
    ).start();
  }, []);

  return (
    
      
    
  );
}

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

Примечание: в этом примере duration = 2000 соответствует 2000 миллисекундам (2 секунды). Если вы хотите ограничить число повторов, передайте iterations в Animated.loop.

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

Чтобы анимация сработала, например, пять раз и остановилась, передайте конфигурацию iterations:

Animated.loop(
  Animated.timing(spinValue, { toValue: 1, duration: 1000, useNativeDriver: true }),
  { iterations: 5 }
).start();

Если iterations опущен, по умолчанию анимация повторяется бесконечно.

Работа со сложными анимациями

Сложные эффекты часто требуют комбинирования нескольких анимаций. Здесь полезны методы Animated.sequence, Animated.parallel, Animated.stagger.

Советы:

  • Разделяйте анимацию на простые части. Это облегчает отладку и повторное использование.
  • Используйте Animated.sequence для поочерёдного исполнения.
  • Используйте Animated.parallel для запуска нескольких анимаций одновременно.
  • Animated.stagger помогает создавать сдвиги во времени между похожими элементами.

Пример: фейд-ин → вращение → фейд-аут, повторяющийся цикл:

const fadeIn = Animated.timing(opacity, { toValue: 1, duration: 300, useNativeDriver: true });
const rotate = Animated.timing(rotation, { toValue: 1, duration: 800, useNativeDriver: true });
const fadeOut = Animated.timing(opacity, { toValue: 0, duration: 300, useNativeDriver: true });

Animated.loop(
  Animated.sequence([fadeIn, rotate, fadeOut])
).start();

Ограничения и тонкости

Важно учитывать следующие ограничения Animated API:

  • useNativeDriver ускоряет анимации, но не поддерживает все свойства (например, layout-свойства типа width/height не анимируются через native driver).
  • Animated.Value лучше хранить в useRef, чтобы избежать пересоздания при каждом рендере.
  • Нужно прекращать анимации при размонтировании компонента, если вы управляете остановкой вручную.

Важно

  • Не пытайтесь анимировать свойства, не поддерживаемые native driver — вместо этого используйте другие способы (например, трансформации для положения и масштаба).

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

Контрпримеры и ситуации, когда стоит выбирать альтернативы:

  • Сложные синхронизированные анимации с множеством независимых таймеров — лучше Reanimated или Lottie.
  • Анимации, затрагивающие layout (изменение высоты/ширины элемента) с большим количеством элементов — layout-изменения лучше обрабатывать отдельными оптимизациями или переходами нативного уровня.
  • Необходимость точного управления кадрами и физически корректного поведения (инерция, сложная физика) — используйте Reanimated 2/3 или physics-движки.

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

  1. Reanimated — современная библиотека, дающая больше контроля и лучшую производительность на нативной стороне.
  2. Lottie — идеален для сложных векторных анимаций, экспортированных из After Effects.
  3. react-native-animatable — быстрые примитивы для распространённых эффектов, проще в интеграции.

Выбор зависит от требований: многократные простые циклы — Animated.loop подходит; сложные визуальные эффекты и высокая производительность — Reanimated/Lottie.

Пошаговая методология для внедрения зацикленной анимации

  1. Определите цель анимации: декоративная ли она или функциональная.
  2. Начните с простого примера (как выше) и убедитесь в работоспособности на устройстве.
  3. Измерьте влияние на FPS и потребление энергии при длительных циклах.
  4. Перенесите Animated.Value в useRef и включите useNativeDriver, если возможно.
  5. Тестируйте на реальных устройствах и в режиме сна/разблокировки экрана.
  6. При необходимости мигрируйте на Reanimated или Lottie.

Чеклист для ролей

Для разработчика:

  • Использовать useRef для Animated.Value.
  • Включать useNativeDriver, когда это возможно.
  • Останавливать/очищать анимации в useEffect cleanup.

Для дизайнера:

  • Определить длительность и тип easing.
  • Предоставить статические кадры и мокапы для проверки переходов.

Для QA:

  • Проверить анимацию при медленном CPU и в энергосберегающем режиме.
  • Проверить доступность: анимация не должна мешать пользователям с чувствительной реакцией.

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

  • Анимация должна плавно повторяться без заметных «прыжков» при стыке цикла.
  • CPU/GPU не должны перегружаться при стандартном использовании приложения.
  • Для количества итераций должно соблюдаться заданное значение iterations (если применимо).
  • При размонтировании компонента анимация должна корректно останавливаться.

Рекомендации по производительности

  • По возможности используйте useNativeDriver: true.
  • Сводите к минимуму создание новых Animated.Values внутри рендера.
  • Избегайте одновременной анимации слишком большого количества элементов.
  • Для тяжёлых векторных анимаций используйте Lottie.

Пример с iterations и остановкой при размонтировании

useEffect(() => {
  const loopAnim = Animated.loop(
    Animated.timing(spinValue, { toValue: 1, duration: 500, useNativeDriver: true }),
    { iterations: 5 }
  );

  loopAnim.start();

  return () => {
    loopAnim.stop();
  };
}, []);

Decision flowchart для выбора инструмента

flowchart TD
  A[Нужна простая зацикленная анимация?] -->|Да| B[Animated.loop]
  A -->|Нет| C[Нужен детальный контроль или физика]
  C --> D[Reanimated]
  C --> E[Нужен вектор/послойный дизайн]
  E --> F[Lottie]

Безопасность и доступность

  • Избегайте интенсивных мерцаний, которые могут вызвать дискомфорт у пользователей с фоточувствительностью.
  • Добавьте опцию в настройках отключения анимаций или уважайте системную настройку “уменьшить движение” (Reduce Motion).

Итог

Animated.loop — удобный инструмент для большинства простых и средних задач по зацикленным анимациям. Он даёт быстрый путь к созданию повторяющегося поведения, но имеет ограничения, особенно когда требуется анимировать layout или достигать сверхвысокой производительности. В таких случаях рассмотрите Reanimated или Lottie. Всегда профилируйте и тестируйте на реальных устройствах.

Важно

  • Помните об accessibility: предоставьте пользователям способ отключить анимации, если это нужно.

Краткое резюме ниже.

Краткое резюме

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

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

Изменение размера фото в Adobe Premiere Pro
Видеомонтаж

Изменение размера фото в Adobe Premiere Pro

Nearby Sharing в Windows 10: быстрый обмен файлами
Windows

Nearby Sharing в Windows 10: быстрый обмен файлами

Медиа‑источник не отображается в OBS — как исправить
OBS

Медиа‑источник не отображается в OBS — как исправить

Поменять папку для скриншотов в One UI 5.1
Mobile

Поменять папку для скриншотов в One UI 5.1

Собрать мощный дешёвый ПК из серверных комплектующих
Сборка ПК

Собрать мощный дешёвый ПК из серверных комплектующих

BitTorrent на Android: как скачивать и делиться
Android.

BitTorrent на Android: как скачивать и делиться