Путешествие в мир анимации с Lottie-React-Native

Вы создаете умопомрачительную анимацию с помощью After Effects и намереваетесь явить ее миру. Один из способов воплотить задуманное  —  использовать ее в качестве экрана-заставки или компонента загрузчика в приложении. Но на вашем пути возникает небольшая проблема: Adobe не разрешает это сделать.

И тут на помощь приходит библиотека lottie-react-native, позволяющая отрисовывать анимации в приложении React Native. А самое главное преимущество состоит в том, что для начала работы достаточно лишь минимального объема кода. 

На основе материала статьи вы научитесь интегрировать библиотеку lottie-react-native в свой проект. Наша конечная цель выглядит так: 

С задачами определились  —  за дело! 

Начальные этапы 

Инициализация проекта 

В текущем проекте используется Expo. Инициализируем приложение React Native, выполняя в терминале следующую команду: 

expo init lottie-tutorial

Установка зависимостей 

Требуемые модули: 

  • lottie-react-native  —  для создания анимации;
  • lottie-ios  —  вложенная зависимость (peer dependency) для отрисовки графики на iOS. 
npm install lottie-react-native [email protected]

Этот этап подготовки пройден, и теперь нам нужны файлы активов. 

Файлы активов  

Вы можете воспользоваться собственной анимацией, экспортировав ее с помощью плагина Bodymovin. Но в данном руководстве мы поработаем с директорией Lottie Files. Она содержит множество бесплатной анимации, которую можно импортировать в проект. Нам интересны две из них: Lava Preloader и Switch Toggle.

Для получения этих активов скачиваем необходимые файлы в формате JSON: 

Затем переносим файлы JSON в каталог assets

Lottie: основы 

В этом разделе вы узнаете об основных принципах этой технологии. 

Простые анимации 

Создаем файл SimpleAnimation.js, в котором пишем следующий код: 

import React from "react";
import { StyleSheet, View } from "react-native";

import LottieView from "lottie-react-native";

export default function SimpleAnimation() {
  return (
    <View>
      <LottieView
        source={require("./assets/67313-lava-preloader.json")}
        style={styles.animation}
      />
    </View>
  );
}
const styles = StyleSheet.create({
  animation: {
    width: 100,
    height: 100,
  },
});
  • Строка 9. Компонент LottieView предназначен для отрисовки анимации. 
  • Строка 10. Свойство source указывает Lottie на расположение актива, подлежащего отрисовке. 
  • Строки 18-19. Высота height и ширина width анимации равняются 100 единицам. 

Теперь осталось только отобразить этот компонент на экране. Для этого в App.js пишем код: 

export default function App() {
  return (
    <View style={styles.container}>
      <SimpleAnimation />
    </View>
  );
}

Получаем результат: 

Объект статичен, поскольку его воспроизведение еще не задано. Приведем его в движение посредством свойства autoPlay:

<LottieView
  source={require("./assets/67313-lava-preloader.json")}
  autoPlay
/* дальнейший код.. */

Полученный результат:

Вот так все просто! 

Анимации загрузчика 

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

Создаем файл LoadingAnimation.js и для начала пишем в нем следующий код: 

export default function LoadingAnimation() {
  const [data, setData] = useState(null);

  const fetchData = async () => {
    const resp = await fetch("https://api.sampleapis.com/coffee/hot");
    const data = await resp.json();
    setData(data);
  };

  useEffect(() => {
    fetchData();
  }, []);

  const Item = ({ title }) => (
    <View style={styles.item}>
      <Text>{title}</Text>
    </View>
  );
  • Строки 4–8. Получаем данные из API и сохраняем их в хуке data
  • Строки 14–18. Компонент Item отвечает за отрисовку каждого элемента списка. 

Далее добавляем к этому же файлу следующий код: 

const renderItem = ({ item }) => <Item title={item.title} />;  
<SafeAreaView>
    {data ? (
      <FlatList
        data={data}
        renderItem={renderItem}
        keyExtractor={(item) => item.id.toString()}
      />
    ) : (
      <LottieView
        source={require("./assets/67313-lava-preloader.json")}
        style={{ width: 100, height: 100 }}
        autoPlay
        loop
      />
    )}
  </SafeAreaView>
);
}
const styles = StyleSheet.create({
  item: {
    backgroundColor: "yellow",
    padding: 20,
    marginVertical: 8,
  },
});
  • Строка 3. Проверяем, загружены ли данные (значение данных не равно null). 
  • Строки 4–8. Отображаем массив data с помощью элемента FlatList
  • Строки 10–15. Если же данные еще загружаются, отображаем анимацию загрузки. 

Получаем результат: 

Отлично! Код работает. Далее научимся управлять другими свойствами анимации. 

Управление скоростью

Для изменения скорости требуется свойство speed

<LottieView
  speed={3}
//дальнейший код..

Скорость анимации увеличивается втрое. 

Уменьшим скорость, установив отрицательное значение: 

<LottieView
  speed={3}
//дальнейший код..

Обработка завершения анимации 

Lottie содержит свойство onAnimationFinish. Напишем функцию обратного вызова, которая будет выполняться по завершении анимации. 

const [finish, setFinish] = useState(false);

const handleFinish = () => {
  setFinish(true);
};
return (
  <View>
    <LottieView
      source={require("./assets/67313-lava-preloader.json")}
      style={styles.animation}
      onAnimationFinish={() => handleFinish()}
      autoPlay
      loop={false}
    />

    <Text>{finish ? "Finished" : "Running.."}</Text>
  </View>
);
  • Строка 11. По завершении анимации вызываем метод handleFinish, вследствие чего для хука finish устанавливается значение true
  • Строка 13. Устанавливаем для свойства loop значение false, в результате чего Lottie выполняет анимацию только один раз. 
  • Строка 16. Применяем условный рендеринг, чтобы указать на завершение анимации. 

Взаимодействие с анимацией

В этом разделе вы узнаете об императивном API Lottie, обеспечивающим более детальное управление активом. 

Воспроизведение и пауза 

Проинструктируем Lottie запускать анимацию при нажатии пальцем на графические объекты и приостанавливать ее при его поднятии. 

Создаем файл InteractiveAnimation.js, где пишем следующий код: 

import React, { useRef, useState } from "react";
import { StyleSheet, View, Pressable, Text } from "react-native";

import LottieView from "lottie-react-native";

export default function InteractiveAnimation() {
  const animation = useRef(null);
  const [pressed, setPressed] = useState(false);
  return (
    <View>
      <Pressable
        onPressIn={() => {
          animation.current.resume();
          setPressed(true);
        }}
        onPressOut={() => {
          animation.current.pause();
          setPressed(false);
        }}
      >
        <LottieView
          ref={animation}
          source={require("./assets/67313-lava-preloader.json")}
          style={styles.animation}
        />
      </Pressable>
      <Text>{pressed ? "Pressed" : "Not pressed"}</Text>
    </View>
  );
}
const styles = StyleSheet.create({
  animation: {
    width: 100,
    height: 100,
  },
});

Разберем данный код.

  • Строка 7. Создаем экземпляр useRef для управления анимацией. 
  • Строка 11. Отрисовываем компонент Pressable, фиксирующий взаимодействия пользователя. 
  • Строки 12–15. Если палец пользователя на экране (onPressIn), возобновляем анимацию. 
  • Строки 16–19. Если пользователь поднял палец (onPressOut), останавливаем анимацию. 
  • Строка 22. Связываем хук animation с этим экземпляром LottieView

Получаем результат:

Переключатели 

В этом разделе применим анимацию переключателя для перехода между состояниями “on” и “off”.

Перед тем как продолжить, изучим файл. Обратите внимание, что графика переходит в положение “on” на Frame 27 и возвращается в “off” на Frame 51 .

Наша задача  —  переключаться между этими кадрами в зависимости от состояния. 

Создаем файл SwitchAnimation.js, в котором пишем следующий код: 

import React, { useEffect, useRef, useState } from "react";
import { StyleSheet, View, Pressable, Text } from "react-native";
import LottieView from "lottie-react-native";

export default function SwitchAnimation() {
  const animation = useRef(null);
  const [on, setOn] = useState(true);

  useEffect(() => {
    if (!on) {
      animation.current.play(0, 27);
    } else {
      animation.current.play(27, 51);
    }
  }, [on]);
  • Строка 6. Создаем хук animation для получения доступа к функциям управления анимацией. 
  • Строка 10. Если состояние не является on, воспроизводим анимацию до Frame 27, что переводит переключатель в состояние “off”. 
  • Строка 12. В противном случае воспроизводим анимацию с Frame 27 по Frame 51, вследствие чего переключатель переходит в состояние “on”. 

Выполнив эту часть задания, добавляем следующий код: 

return (
    <View>
      <Pressable onPress={() => setOn((old) => !old)}>
        <LottieView
          ref={animation}
          source={require("./assets/67255-switch-toggle.json")}
          style={styles.animation}
          loop={false}
          autoPlay={false}
        />
      </Pressable>
      <Text> {on ? "On" : "Off"}</Text>
    </View>
  );
}
const styles = StyleSheet.create({
  animation: {
    width: 100,
    height: 100,
  },
});
  • Строка 3. При нажатии значение хука on меняется на противоположное. 

Полученный результат:

Миссия выполнена! 

Весь код можно найти на GitHub.

Заключение 

Если вы ищите простую в использовании библиотеку анимации, то Lottie отлично подойдет для вашего приложения. И конечно, вы оцените тот факт, что вам не нужно перестраивать анимации посредством кода, вследствие чего можно сосредоточиться на более важных частях проекта. 

Читайте также:

Читайте нас в Telegram, VK и Яндекс.Дзен


Первод статьи Hussain Arif: How To Create Animations With Lottie-React-Native

Предыдущая статья5 крутых приемов, которые улучшат работу на R
Следующая статьяВек программируй, век учись