Привет, Хабр. Меня зовут Алексей, я разрабатываю мобильные приложения на Flutter в Пиробайте. Помимо этого увлекаюсь моушн-дизайном. В прошлый раз я рассказывал о том, почему Flutter Web (не) мертв. Сегодня предлагаю продолжить наш тру-крайм в мире разработки и снова узнать кто кого убил, за что убил и убил ли вообще. Наш сегодняшний герой — инструмент для создания анимации Rive.
Если в предыдущей статье главная жертва была в общем-то беззащитна и легко пала под натиском убийцы, то в этот раз все гораздо сложнее и запутаннее: противостояние этих двух платформ — Lottie и Rive — можно назвать напряженным психологическим триллером о политике. И я сейчас объясню почему.
Lottie — крайне полезный инструмент для создания анимации, однако далеко не идеальный. А когда у основного игрока начинают появляться проблемы, появляются те, кто с удовольствием начинают на него давить. Медленно, но верно подтачивая ноги глиняного колосса.
Что за Rive и в чем претензия к Lottie
Rive — это также инструмент для создания анимации под разные платформы. А главная, пожалуй, претензия к Lottie — это использование стороннего софта для анимации (After Effects), высокая нагрузка на устройства (если мы говорим про код на мультиплатформе) и полное отсутствие работы с интерактивностью (дизайнер полагается только на разработчика).
Однако, как в мир дизайна пришла Figma, так и в мир интерактивной анимации врывается Rive. Почему именно такое сравнение? А давайте просто взглянем на дизайн интерфейса Rive:
Вместо фрейма тут артборд, а вместо Dev Mode — Аnimate. Все остальное буквально взято из Фигмы, и не случайно. Так разработчики пытаются сделать переход на Rive максимально комфортным для всех дизайнеров.
Ну что, давайте попробуем что-нибудь анимировать?
И заодно познакомимся с основными киллерфичами Rive. Для примера нарисуем вот такую кнопку:
Все те же слои и свойства как в Figma (нарисовал я ее в Rive и ниоткуда не экспортировал, прошу заметить).
Есть верхняя часть кнопки (цвет и текст), а есть нижняя, которая является тенью. И дальше перейдем к анимации, но сначала снова небольшое отступление.
Главная фича Rive — это наличие State Machine. Что это такое? Процитируем документацию:
State machine — это визуальный способ связать анимацию с логикой, которая определяет переходы между анимацией. Они позволяют создавать интерактивную графику в движении, готовую к внедрению в ваш продукт, приложение, игру или веб-сайт. State machine — это новый уровень коллаборации между дизайнерами и разработчиками, который и тем и другим позволяет глубже погрузиться в процесс разработки.
State machine помогает дизайнеру расписать логику когда и то, как вызывать анимацию. Этой логикой может воспользоваться разработчик, чтобы перенести все это в код.
А теперь вернемся к нашей кнопке. Давайте реализуем действие по нажатию на кнопку. С чего начать? Ну, разумеется с вкладки Animate.
Что мы видим? Тот самый State Machine. Если кто-то работал с Cinema 4D, то у него будут флешбэки (надеюсь, не вьетнамские). Но пока нам это не интересно, так как у нас нет анимации, а значит, нет никакой логики взаимодействия с этой анимацией.
Поэтому на вкладке Animations (там, где State Machine) нажимаем на плюсик и выбираем Timeline.
Внутри мы видим уже другой флешбэк (ну что за день!), однако вспоминаем уже AfterEffects. И чтобы не делать кучу скриншотов, сразу покажу почему это так похоже на AE и сделаю небольшую анимацию.
Мы находимся все в том же Rive и работаем с ключевыми кадрами. Никаких новых концепций (что просто потрясающе!), если вы уже работали с AE.
Анимация выглядит так:
Также нужно реализовать Idle анимацию (создайте новый таймлайн и просто сбросьте все ключевые кадры), чтобы у кнопки было состояние покоя (как мы тебя понимаем, кнопочка).
Для начала перетаскиваем состояние покоя в рабочее пространство (да, опять работать) и создаем связь между ними (просто тянем за краешек Entry, входной точки анимации).
То же самое проделываем с анимацией клика. А дальше самое интересное, следите за руками :)
Слева от рабочего пространства у нас есть вкладки Listeners и Inputs. Listeners — это наши слушатели, которые следят за тем или иным действием. У нас это действие называется клик. А что должно двигаться по клику? Верхний слой кнопки, поэтому мы сначала выделяем наш Front-слой, а потом на плюсик у Listeners. Меняем дефолтное имя на Click и вуаля!
А за чем следим-то?
Найдем ответ справа. Предлагаю вспомнить все знания английского и подумать — а какое событие нам нужно? На скриншоте спойлер, да, поэтому конечно Pointer Down, когда курсор нажимается на объект.
А что делать, когда происходит Pointer Down? Бахайте из всех ружей под названием клик (буквально fire: click, как на скриншоте).
Окей, слушатель у нас есть. Ему, конечно, очень интересно, но в то же время и непонятно, а когда стрелять из хлопушки? Правильный ответ — когда ему махнут флажком, дадут сигнал. А значит, нам этот флажок нужно создать! Пошли в Inputs.
И там выбираем тип сигнала, по которому что-то случится. Тут все просто — нажатие происходит по клику, прям как нажатие на курок, а курок — это триггер… Выбираем триггер (многовато их в последнее время, да). И называем его click.
Окей, сигнал создали. Однако он пока просто пылится за кулисами, а слушатель про него ни сном, ни духом. Давайте уточним для него инструкцию. Если происходит нажатие на курок, то стреляй. В программе это будет выглядеть так:
Теперь есть связь: кнопка в покое, происходит хлопок. Слушатель понимает, что нужно действовать и запускает анимацию click.
Круто! Мы уже можем запустить нашу анимацию. Нажмите на Idle, затем пробел, а потом кликнете по кнопке.
Очень круто, но хочется еще, ведь кнопка тыкнется только один раз. Значит, нам нужно закольцевать нашу анимацию. От click создаем связь к Idle, нажимаем на эту связь, видим Duration и ставим его на 100%.
Вот и все, кнопка готова. Теперь экспортируем ее и передаем разработчику!
Дальше начинается магия для разработчиков
Благодаря тому, что дизайнер подумал заранее и правильно назвал все слушатели и инпуты (а еще желательно State Machine переименовать в человеко-понятное, типа Button Animation), мы четко понимаем, что должны использовать в коде.
И так как я разрабатываю на Flutter, то и пример будет на Flutter. Однако не забывайте, что Runtime у Rive рассчитан на любую платформу и на каждую есть своя отдельная библиотека. В нашем случае это rive.
Не будем останавливаться на очевидном. Устанавливаем пакет, кидаем .riv файл в assets, прописываем их в пабспеке. Все по классике.
Работа начинается с инициализации контроллера. Чтобы упростить дальнейшую работу, мы сделаем класс RiveUtils и инициализируем его там.
Далее переходим к виджетам. Так как мы знаем, что в дизайне использовался триггер, то мы его и прописываем:
Далее используем класс RiveAnimation.asset.
И все! В этом вся прелесть работы с ассетами Rive.
Помимо удобства работы с самим софтом, формат .riv также отличается скоростью работы.
Есть неплохое сравнение быстродействия Lottie и .riv, причем одной и той же анимации (взято из документации):
File size: 18 KB (no compression)
GPU Memory: 2.6 MB
JS heap: 7.3 MB
CPU: 31.8%
File size: 181.7 KB (no compression)
GPU Memory: 149-190 MB
JS heap: 16.9 MB
CPU: 91.8%
Ну не может же быть все так идеально, верно? Все-таки этот инструмент находится в бете. Хотя активно развивается и разрабатывает его не один человек, а целая команда.
Какие минус я выделил для себя?
Со стороны дизайна:
Когда мы работаем с кривыми в AfterEffects, то можем управлять ими на протяжении всей анимации в редакторе кривых. Мы видим эти кривые как часть всей анимации. В Rive же такого нет — можем работать с кривыми только у каждого отдельного ключевого кадра. Никакого общего графика значений.
Это не бесплатный инструмент. Да, бесплатный тариф позволяет полноценно работать с ним. Но, во-первых, это ограничение до 3-х дизайнов на аккаунт. Во-вторых, невозможность использовать кастомные шрифты. В третьих — на бесплатном аккаунте нельзя работать в команде (в отличии от той же Фигмы). В платном аккаунте такая возможность есть.
Со стороны разработки:
Если вы мобильный разработчик, а у кнопки есть откровенно ненужный вам ховер, он будет отрабатывать по нажатию. И тут либо иметь 2 версии кнопок (с ховером для сайта и без ховера для мобилки) или, в случае Flutter, оборачивать их в GestureDetector и в ручную задавать значение false у булевого поля (обычно ховер это именно булевое), когда происходит нажатие (а много GestureDetector — это плохо).
Если подытожить, то инструмент крайне интересный и позволяет упростить взаимодействие дизайнеров и разработчиков. У Rive есть все шансы стать Figma в мире анимаций, так как он крайне удобен для дизайнеров.
***
Будем ли мы использовать его у нас в студии? Хороший вопрос, однако мы пока в раздумьях. Но если вы и сами работали с Rive или зашли защитить Lottie, то было бы здорово услышать ваше мнение в комментариях!