Привет! Меня зовут Никита Грибков, я Flutter-разработчик в AGIMA. Расскажу вам про возможности Rive — фреймворка, который использует векторную графику для создания анимации во Flutter-приложениях. Эта статья выросла из небольшого поста на Хабре, в котором я коротко описал опыт работы над кнопкой для Bottom Bar в своем пет-проекте. Здесь же я уже подробно опишу, как анимировать элементы и чем вообще хорош Rive.

Почему Rive

Когда я впервые столкнулся с необходимостью добавить анимацию во Flutter-приложение, выбор, само собой, пал на Lottie. Это вид анимации, который тогда пользовался популярностью. И хотя внедрить его в проект было непросто, кастомный лоадер был установлен. И надо отдать ему должное — он отлично работал.

Однако вскоре алгоритмы Google подкинули мне информацию о RIve. Это еще один формат анимации, который, как оказалось, намного больше подходил под наши бизнес-задачи. И самые убедительные аргументы тому мы нашли прямо в документации Rive:

Пример веб-сайта Lottie

Пример веб-сайта Rive

Размер файла: 181,7 КБ (без сжатия)

Память графического процессора: 149–190 МБ

Куча JS: 16,9 МБ

ЦП: 91,8%

Размер файла: 18 КБ (без сжатия)

Память графического процессора: 2,6 МБ

Куча JS: 7,3 МБ

ЦП: 31,8%

Как видим, создатели Rive позаботились о том, чтобы анимация была легче и быстрее. Мы с командой прикрутили Rive-лоадер, и вскоре поняли, что управлять анимацией стало в разы проще, а User-flow стал удобнее. Ниже рассказываю про основные инструменты Rive, а в конце объясню, в каких случаях его лучше всего применять.

Преимущества Rive

При разработке Flutter-приложений вообще используют много типов анимации, мы уже писали об этом в отдельной статье. Но на мой взгляд, Rive превосходит большинство из них. Во-первых, мне нравится встроенный UI-интерфейс. Во-вторых, в Rive есть раздел Community, где авторы выкладывают бесплатные анимации.

А в-третьих, — и это главное преимущество — в Rive есть State Machine. Это визуальный способ связать анимацию воедино и определить логику, которая управляет переходами. State Machine позволяет создавать интерактивную графику движения, готовую к внедрению в ваш продукт, приложение, игру или веб-сайт.

State Machine включает несколько уровней:

  • Graph (График) — это пространство, в котором мы будем добавлять состояния и соединять переходы. Он появляется вместо временной шкалы, когда машина состояний выбрана в списке анимаций.

  • State — это просто анимации временной шкалы, которые могут воспроизводиться в нашей машине состояний. Как правило, они представляют собой некоторое состояние, в котором находится ваш анимированный контент.

  • Transaction — переходы представляют собой логическую карту для State Machine. Существует ряд соображений и настраиваемых свойств для переходов.

  • Inputs — это договор между дизайнерами и разработчиками. Как дизайнеры, мы используем входы как способ управления переходами в нашей машине состояний, назначая их в качестве условий. Разработчики связываются с входами во время выполнения и определяют условия с помощью кода, который может изменить эти входы.

  • Layers — слой State Machine, который позволяет воспроизводить одну анимацию за раз. По этой причине вы можете создать несколько слоев, если хотите смешать несколько анимаций или добавить дополнительные взаимодействия в State Machine.

Инструменты Rive

Для работы с Rive Animation лучше использовать их UI-интерфейс, в котором и происходит создание и настройка самой анимации. Анимация состоит из нескольких составляющих. Они больше знакомы дизайнерам, но, если кратко, вот некоторые из них.

  1. Artboard: слой, который является холстом анимации на котором располагаются остальные элементы. В нем можно задать цвет и размер фона. В каждом файле Rive есть хотя бы один такой.

  2. Group: необязательный элемент, но он отлично подходит, чтобы объединить элементы в группы для любого объекта, изменение которого может потребоваться в дальнейшем.

  3. Shape: Rive позволяет создавать, редактировать и анимировать векторную графику, используя процедурные или пользовательские фигуры. Из них чаще всего и состоит весь интерфейс. Также есть крутой инструмент Pen.

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

Три вида операторов, которые используются для триггера анимации

Number

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

Допустим, у нас есть анимация загрузки, которая активируется, когда счетчик достигает определенного значения. Для начала создаем контроллер и каунтер:

RiveAnimationController _controller; 
int _counter = 0;

Затем создаем метод, в котором будем обрабатывать состояние в зависимости от значение _counter.

void _incrementCounter() {
    setState(() {
        _counter++;
        if (_counter >= 10) {
            _controller = SimpleAnimation('loading');
        } else {
            _controller = SimpleAnimation('idle');
        }
    });
}

После этого создаем контейнер с нашим ассетом и добавляем ElevatedButton с методов _incrementCounter.

Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
        SizedBox(
            width: 200,
            height: 200,
            child: RiveAnimation.asset(
                'assets/loading_animation.riv',
                controllers: [_controller],
                fit: BoxFit.cover,
            ),
        ),
        ElevatedButton(
            onPressed: _incrementCounter,
            child: Text('Increment Counter: $_counter'),
        ),
    ],
),

Bool

Каждый разработчик знает об этом операторе. Он может быть True или False. В зависимости от значения логического оператора обрабатывает логику анимации.

Для Bool-оператора всё тривиально. Думаю, комментарии тут излишни. Так бы выглядел код всё с тем же лоадингом:

RiveAnimationController _controller;
bool _isPlaying = false;

void _toggleAnimation() {
    setState(() {
        _isPlaying = !_isPlaying;
        if (_isPlaying) {
            _controller = SimpleAnimation('play');
        } else {
            _controller = SimpleAnimation('idle');
        }
    });
}
Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
        SizedBox(
            width: 200,
            height: 200,
            child: RiveAnimation.asset(
                'assets/toggle_animation.riv',
                controllers: [_controller],
                fit: BoxFit.cover,
            ),
        ),
        ElevatedButton(
            onPressed: _toggleAnimation,
            child: Text(_isPlaying ? 'Pause' : 'Play'),
        ),
    ],
),

Trigger

Триггеры аналогичны логическим значениям, но могут стать истинными только на короткое время.

С триггером мы получаем чуть больше кода, так как триггеры могут быть заданы разные и надо их обрабатывать из самого ассета. 

 Artboard _artboard;
 RiveAnimationController _controller;

 void _triggerAnimation() {
     if (_controller != null) {
         _artboard.artboard.removeController(_controller);
     }
     _controller = SimpleAnimation('trigger');
     _artboard.artboard.addController(_controller);
 }
@override
void initState() {
    super.initState();
    _rootBundle();
}
void _rootBundle() {
    rootBundle.load('assets/trigger_animation.riv').then((data) {
        final file = RiveFile.import(data);
        final artboard = file.mainArtboard..addController(SimpleAnimation('idle'));
        setState(() => _artboard = artboard);
    });
}
Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
        _artboard != null ?
        Rive(
            artboard: _artboard,
            fit: BoxFit.cover,
        ) :
        SizedBox(),
        ElevatedButton(
            onPressed: _triggerAnimation,
            child: Text('Trigger Animation'),
        ),
    ],
),

Вывод

В итоге Rive-анимацией мы закрыли все кейсы, когда в приложении заказчика нужно было проигрывать анимацию. Сейчас Rive в наших проектах используется повсеместно как основной инструмент анимации. Хотя и про Lottie мы иногда вспоминаем.

  • Rive отлично подходит, если ваша анимация должна быть интерактивной или требует сложной логики и взаимодействия.

  • Lottie лучше использовать, если вам нужны простые и легкие анимации, которые легко интегрировать в многоплатформенные приложения.

Если у вас остались вопросы про Rive — буду рад ответить в комментариях. Также подписывайтесь на канал нашего руководителя направления мобильной разработки Саши Ворожищева — у него много про Flutter.

Что еще почитать

Комментарии (2)


  1. Kerrigan
    10.07.2024 12:06

    Главный минус rive это отсутствие любого способа создавать анимации кроме как через облачный сервис, который завтра может закрыться и ваши наработки превратятся в тыкву


  1. muryk
    10.07.2024 12:06

    Я лично отказался от Rive как только увидел что он добавляет что-то около 40мб (точнее не помню) к бинарнику. Должен же быть какой-то предел всей этой инфляции.