Fonctionnement des animations dans React Native

React Native est un excellent framework qui vous permet de créer des applications mobiles multiplateformes. C'est particulièrement utile si vous êtes un développeur Web et que vous souhaitez une solution rapide et peu coûteuse pour développer des applications mobiles natives qui fonctionnent à la fois sur Android et iOS. Bonus: vous n'avez pas à dépenser $$$ sur des équipes iOS, Android et Web distinctes.

Cela réduit non seulement vos coûts, mais vous permet également de partager une partie de votre base de code entre les trois versions (Android, iOS et Web), ce qui facilite les modifications et le déploiement des mises à jour.

React Native vous permet également de travailler assez près du système d'exploitation réel, ce qui est important pour les tâches essentielles aux performances telles que les animations.

Les animations font partie intégrante de toute application car elles la rendent interactive et plus attrayante pour l'utilisateur final. Mais souvent, lorsque vous travaillez avec des animations, vous pouvez avoir l'impression de travailler avec une boîte noire.

Voyons donc comment fonctionnent les animations dans React Native. Vous pouvez commencer à apprendre des animations dans React Native à partir de zéro à partir de cette liste de lecture YouTube gratuite.

L'API animée

React Native expose une API appelée Animated. Il se compose de beaucoup de choses merveilleuses comme des valeurs animables, des animations de printemps / chronométrage et des événements. Mais nous ne sommes pas ici pour discuter de l'API - je laisserai cela aux documents officiels et à ma playlist YouTube. Ils font un bien meilleur travail en couvrant cela pour vous.

Ce dont nous voulons discuter ici, en fait, c'est comment React Native anime des choses à l'écran et ce qui se passe sous le capot.

Deux façons d'animer

Vous devriez savoir comment React Native fonctionne sous le capot de mon autre article. (Lisez-le rapidement si vous ne l'avez pas déjà fait.) Puisque React Native utilise React et JavaScript, il existe précisément 2 façons d'exécuter des animations à l'écran.

Tout d'abord, clarifions un fait. React Native construit des vues natives réelles à l'écran, et non celles rendues via des navigateurs Web intégrés comme Ionic. Pour cette raison, si vous souhaitez animer une vue de quelque manière que ce soit, cela doit finalement être fait sur la vue native.

JavaScript doit communiquer avec le système d'exploitation d'une certaine manière que la vue doit être mise à jour. JavaScript s'exécute dans un thread différent de celui de l'interface utilisateur (thread principal), et seul ce thread d'interface utilisateur peut mettre à jour les vues. JS doit donc utiliser le pont fourni par React Native pour sérialiser et communiquer ces données au système d'exploitation.

Travaillez dans JS et mettez à jour la vue native

Cette approche signifie que vous prenez une vue qui est déjà visible sur l'écran de l'utilisateur et que vous travaillez sur ce qui doit être fait pour sa prochaine position dans le thread JavaScript. Les étapes ressemblent à peu près à ceci:

  1. L'animation démarre
  2. JavaScript exécute la requestAnimationFramefonction - une fonction qui essaie de s'exécuter à 60 appels / seconde (60 FPS)
  3. JavaScript calcule la prochaine position / opacité / transformation / tout ce que vous animez sur la vue.
  4. JavaScript sérialise cette valeur et l'envoie sur le pont.
  5. A l'autre bout du bridge, Java (Android) ou Objective C (iOS) désérialise cette valeur et applique les transformations données sur la vue mentionnée.
  6. Le cadre est mis à jour à l'écran.

Avez-vous vu ce qui s'est passé là-bas? Aucune des étapes ne rend réellement un composant React Native. Cela signifie que l'API animée "contourne" la philosophie de React de ne pas muter les variables "d'état".

La bonne nouvelle: c'est en fait utile en cas d'animations car ce sera beaucoup trop lent et mauvais pour les performances si nous laissons React re-rendre un composant 60 fois par seconde!

Tout cela est beau et bon, mais il y a un problème très fondamental ici. JavaScript est à thread unique. La nature asynchrone de JavaScript ne fonctionne donc pas ici car les animations sont une tâche liée au processeur. Jetons un coup d'œil aux avantages et aux inconvénients de cette approche.

Avantages

  1. Vous pouvez avoir des animations très sophistiquées écrites en JS et visibles sous forme d'animations natives.
  2. Plus de contrôle sur l'état de l'animation

Les inconvénients

  1. Énorme pénalité de performances si votre thread JavaScript est très occupé.
  2. Si le pont est occupé, les performances diminuent lorsque le système d'exploitation / JS souhaite communiquer entre eux.

Ce con est un gros con pour être honnête. Il y a une vidéo plus bas dans l'article qui vous montre ce problème en temps réel. Vous verrez à quel point JS se passe beaucoup de temps avec des animations lorsque le thread JavaScript devient occupé.

Pourquoi les animations JS sont-elles décalées?

Les animations effectuées dans JS commenceront à être retardées lorsque l'animation est en cours et que l'utilisateur (ou l'application) demande une autre action qui doit être gérée par le thread JS.

Par exemple, imaginez qu'une animation se produise. Cela signifie que JS est occupé à exécuter la requestAnimationFramefonction. En supposant que les mises à jour ne sont pas elles-mêmes trop lourdes, supposons qu'un utilisateur commence à appuyer sur un bouton à l'écran qui incrémente un compteur.

Maintenant, avec l' requestAnimationFrameappel fréquemment, votre arbre virtuel React est également re-rendu encore et encore afin de tenir compte de l'augmentation du compteur.

Les deux sont des tâches liées au processeur s'exécutant sur un seul thread, il y aura donc un impact sur les performances. requestAnimationFramecommencera à supprimer des images en raison du travail supplémentaire effectué par le thread JS.

Tout cela signifie que vous obtiendrez une animation très saccadée.

Animations de pilotes natifs

Ne vous inquiétez pas, car React Native vous permet également d'exécuter des animations sur le pilote natif! Qu'est-ce que je veux dire par là, pourriez-vous demander?

Eh bien, tout simplement, cela signifie que React Native décharge le travail d'animation du thread JS vers le thread d'interface utilisateur (le système d'exploitation) et lui permet de gérer l'animation de l'objet. Cela présente quelques avantages:

  1. Le thread JS (et le pont React Native) est désormais gratuit pour gérer d'autres tâches intensives telles que les taps répétitifs de l'utilisateur.
  2. Les animations sont beaucoup plus fluides car il n'y a pas de sérialisation / désérialisation et de surcharge de communication de pont.

Comment React Native y parvient-il? Les gens de React Native vous permettent en tant que développeur de fournir une propriété appelée useNativeDrivercomme valeur booléenne lorsque vous construisez un objet d'animation.

Lorsqu'il est défini sur true, React Native, avant de démarrer l'animation, sérialise l'ensemble de l'état de l'animation et ce qui doit être fait à l'avenir. Il le transfère ensuite une fois sur le pont vers le système d'exploitation.

À partir de là, le code Java (Android) ou Objective C (iOS) exécute les animations au lieu de JavaScript calculant l'image d'animation suivante et envoyant ces données encore et encore sur le pont.

Cela accélère beaucoup les animations et les animations fonctionnent plus facilement, en particulier sur les appareils bas de gamme. Voyons une démonstration vidéo des animations natives et des animations basées sur JS dans React Native:

Dans ce cas, les étapes ressemblent à peu près à ceci:

  1. L'animation démarre
  2. JS sérialise les informations d'animation et les envoie sur le pont.
  3. À l'autre extrémité, le système d'exploitation reçoit ces informations et exécute l'animation de manière native.

C'est ça! Les animations sont désormais beaucoup plus légères pour le thread JS. Plus requestAnimationFramebesoin de courir sans fin.

Cependant, cette méthode a sa propre part d'avantages et d'inconvénients.

Avantages:

  1. Animations plus rapides
  2. Filetage JS non bloquant
  3. Pont moins gonflé

Les inconvénients:

  1. Moins de contrôle sur les animations (JS ne peut pas voir ce qui se passe à l'écran une fois que l'animation "automatique" démarre)
  2. Moins de propriétés à manipuler - le pilote natif ne prend pas en charge toutes les propriétés à animer. Par exemple,   widthou heightne sont pas animables nativement, mais opacityet transformsont.

Dans de nombreux cas, vous constaterez que vous pouvez contourner un ensemble différent d'animations en utilisant useNativeDriver: truepour créer un effet similaire qui ne peut pas être obtenu sans réglage useNativeDriver: false.

L'équipe React Native travaille actuellement sur l'ajout de la prise en charge de plus de propriétés, mais pour l'instant, je pense que cela fonctionne très bien pour le moment.

Conclusion

Cet article vous a montré comment les animations React Native fonctionnent réellement sous le capot et pourquoi elles sont belles.

Que penses-tu de cet article? Dites-moi en me connectant sur mes comptes Instagram et Twitter! Nouveau sur React Native? Commencez à l'apprendre sur codedamn - une plate-forme permettant aux développeurs d'apprendre et de se connecter!

Paix!