Як працюють анімації у React Native

React Native - чудовий фреймворк, який дозволяє створювати крос-платформні мобільні додатки. Це особливо корисно, якщо ви веб-розробник і хочете швидке, недороге рішення для розробки власних мобільних додатків, які працюють як на Android, так і на iOS. Бонус: вам не потрібно витрачати $$$ на окремі команди iOS, Android та веб.

Це не тільки зменшує ваші витрати, але також дозволяє поділитися частиною кодової бази між усіма трьома збірками (Android, iOS та Web), полегшуючи внесення змін та розгортання оновлення.

React Native також дозволяє працювати досить близько до фактичної ОС, що важливо для критично важливих завдань, таких як анімація.

Анімація є невід’ємною частиною будь-якого додатка, оскільки робить його інтерактивним та привабливим для кінцевого користувача. Але багато разів, працюючи з анімацією, ви можете відчути, що працюєте з чорною скринькою.

Тож давайте дізнаємось, як анімація працює в React Native. Ви можете розпочати вивчення анімації в React Native з нуля з цього безкоштовного списку відтворення YouTube.

Анімований API

React Native пропонує API, який називається Animated. Він складається з багатьох чудових речей, таких як анімаційні цінності, весняна / хронометражна анімація та події. Але ми не тут, щоб обговорювати API - я залишу це в офіційних документах та своєму списку відтворення на YouTube. Вони роблять набагато кращу роботу, висвітлюючи це для вас.

Тут ми хочемо обговорити насправді те, як React Native анімує речі на екрані і що відбувається під капотом.

Два способи оживлення

Ви повинні знати, як React Native працює під капотом з іншої моєї статті. (Швидко прочитайте, якщо ви цього ще не зробили.) Оскільки React Native використовує React та JavaScript, існує точно 2 способи здійснення анімації на екрані.

Перш за все, давайте прояснимо один факт. React Native створює фактичні власні подання на екрані, а не ті, що відображаються за допомогою вбудованих веб-браузерів, таких як Ionic. Через це, якщо ви хочете будь-яким чином анімувати подання, це в кінцевому підсумку має бути зроблено на рідному поданні.

JavaScript повинен взаємодіяти з ОС певним чином, що подання потрібно оновити. JavaScript працює в іншому потоці, ніж потік інтерфейсу користувача (основний потік), і лише цей потік інтерфейсу може оновлювати подання. Отже, JS потрібно використовувати міст, який React Native надає для серіалізації та передачі цих даних в ОС.

Попрацюйте в JS та оновіть власний вигляд

Цей підхід означає, що ви берете подання, яке вже видно на екрані користувача, і працюєте над тим, що потрібно зробити для його наступної позиції в потоці JavaScript. Кроки приблизно виглядають так:

  1. Починається анімація
  2. JavaScript запускає requestAnimationFrameфункцію - функцію, яка намагається працювати зі швидкістю 60 викликів в секунду (60 кадрів в секунду)
  3. JavaScript обчислює наступну позицію / непрозорість / перетворення / все, що ви анімуєте у поданні.
  4. JavaScript серіалізує це значення та надсилає його через міст.
  5. На іншому кінці мосту Java (Android) або Objective C (iOS) десеріалізує це значення та застосовує дані перетворення у згаданому поданні.
  6. Кадр оновлюється на екрані.

Ви бачили, що там сталося? Жоден із кроків насправді не відтворює компонент React Native. Це означає, що анімований API насправді "обходить" філософію React щодо немутації змінних "стану".

Хороша новина: це насправді корисно у випадку анімації, оскільки це буде занадто повільно і погано для продуктивності, якщо ми дозволимо React повторно відтворити компонент 60 разів на секунду!

Це все приємно і добре, але тут є дуже фундаментальна проблема. JavaScript є однопоточним. Отже, асинхронна природа JavaScript тут не працює, оскільки анімація - це завдання, пов’язане з процесором. Давайте розглянемо плюси і мінуси цього підходу.

Плюси

  1. Ви можете створити дуже вишукані анімації, написані на JS, і видимі як власні анімації.
  2. Більший контроль над станом анімації

Мінуси

  1. Величезне покарання за продуктивність, якщо ваш потік JavaScript дуже зайнятий.
  2. Якщо міст зайнятий, знижується продуктивність, коли ОС / JS хочуть спілкуватися між собою.

Цей шахрай - це великий шахрай, якщо чесно. Далі в статті є відео, яке насправді відображає цю проблему в режимі реального часу. Ви побачите, як JS затягує анімації, коли потік JavaScript стає зайнятим.

Чому анімація JS відстає?

Анімація, виконана в JS, почне відставати, коли триває анімація, і користувач (або додаток) вимагає іншої дії, яку повинен обробляти потік JS.

Наприклад, уявіть, що відбувається анімація. Це означає, що JS зайнятий запуском requestAnimationFrameфункції. Припускаючи, що оновлення самі по собі не надто важкі, припустимо, користувач починає натискати кнопку на екрані, яка збільшує лічильник.

Тепер, requestAnimationFrameколи вас часто викликають, ваше віртуальне дерево React також повторно відображає знову і знову, щоб врахувати збільшений лічильник.

Обидва вони є завданнями, пов’язаними з процесором, що працюють в одному потоці, тому буде вражати продуктивність. requestAnimationFrameпочне скидати кадри через додаткову роботу, виконану потоком JS.

Все це означає, що ви отримаєте дуже різку анімацію.

Анімація рідного драйвера

Не хвилюйтеся, адже React Native насправді дозволяє запускати анімацію і на рідному драйвері! Ви можете запитати, що я маю на увазі під цим?

Ну, простіше кажучи, це означає, що React Native розвантажує роботу анімації з потоку JS в потік інтерфейсу користувача (ОС) і дозволяє їй обробляти анімацію об'єкта. Це має кілька переваг:

  1. Потік JS (і мост React Native) тепер безкоштовний для обробки інших інтенсивних завдань, таких як повторювані натискання від користувача.
  2. Анімація набагато плавніша, оскільки немає серіалізації / десериалізації та мостового зв'язку.

Як це реагує React Native? Люди в React Native дозволяють вам як розробнику надавати властивість, що називається useNativeDriverбулевим значенням, коли ви створюєте анімаційний об'єкт.

Якщо встановлено значення true, React Native перед початком анімації серіалізує весь стан анімації та те, що потрібно зробити в майбутньому. Потім він передає його один раз через міст до ОС.

Відтепер код Java (Android) або Objective C (iOS) запускає анімації замість JavaScript, обчислюючи наступний анімаційний кадр і надсилаючи ці дані знову і знову по мосту.

Це значно пришвидшує анімацію, і анімація працює більш плавно, особливо на низькокласних пристроях. Давайте подивимося відеодемонстрацію власних анімацій проти анімацій на основі JS у React Native:

У цьому випадку кроки приблизно виглядають так:

  1. Починається анімація
  2. JS серіалізує інформацію про анімацію та надсилає її через міст.
  3. З іншого боку, ОС отримує цю інформацію та виконує анімацію.

Це воно! Анімація набагато легша для потоку JS. Більше не requestAnimationFrameбігати нескінченно.

Однак у цього методу є своя частка плюсів і мінусів.

Плюси:

  1. Швидша анімація
  2. Неблокуючий потік JS
  3. Менш роздутий міст

Мінуси:

  1. Менший контроль над анімацією (JS ​​не може бачити, що відбувається на екрані після запуску "автоматичної" анімації)
  2. Менше властивостей для маніпулювання - власний драйвер не підтримує всіх властивостей, які потрібно анімувати. Наприклад,   widthабо heightне є рідними для анімації, але opacityі transformє.

У багатьох випадках ви виявите, що ви можете обійти інший набір анімацій, використовуючи, useNativeDriver: trueщоб створити подібний ефект, якого неможливо досягти без налаштування useNativeDriver: false.

Команда React Native працює над додаванням підтримки для більшої кількості властивостей, поки ми говоримо, але наразі я вважаю, що це працює на даний момент.

Висновок

Ця стаття показала вам, як React Native анімація насправді працює під капотом і чому вона чудова.

Що ви думаєте про цю статтю? Скажіть мені, зв’язавшись зі мною в моїх акаунтах Instagram та Twitter! Новачок у React Native? Почніть вивчати його на codedamn - платформі для вивчення та підключення розробників!

Мир!