L'animation est une partie importante de la conception de l'expérience utilisateur. Il sert de retour d'informations sur les actions des utilisateurs, informe les utilisateurs de l'état du système et les guide sur la manière d'interagir avec l'interface..
React Native est l'un des outils que j'utilise pour créer des applications mobiles multi-plateformes. Dans ce didacticiel, je vais vous expliquer comment implémenter des animations sur cette plate-forme. La sortie finale de ce tutoriel sera une application pour évier de cuisine qui implémentera différents types d'animations. Voici à quoi cela ressemblera:
Je présumerai que vous connaissez déjà les bases du travail avec React Native. Par conséquent, je ne vais pas trop approfondir le code qui n'a rien à voir avec les animations. Pour plus d'informations sur React Native, consultez certains de mes autres tutoriels..
Nous travaillerons spécifiquement sur la plate-forme Android, mais le code utilisé dans ce tutoriel devrait également fonctionner sur iOS. En fait, si vous ne souhaitez pas gérer la douleur liée à la configuration d'un nouveau projet React Native, je vous recommande de consulter React Native Web Starter. Cela vous permet de créer un nouveau projet React Native que vous pouvez prévisualiser dans le navigateur. Cela présente l'avantage de ne pas avoir à configurer un périphérique et un rechargement à chaud plus rapide afin que vous puissiez prévisualiser vos modifications plus rapidement..
Si vous ne l'avez pas déjà fait, créez un nouveau projet React Native:
réact-native init RNAnimation
Si vous utilisez React Native Web Starter, voici comment créer un nouveau projet:
clone de git https://github.com/grabcode/react-native-web-starter.git cn RNA RNAnimation rm-rf .git npm installer
Ouvrez le index.android.js (ou index.web.js), Supprimez le code par défaut et ajoutez ce qui suit:
importer Réagir, Composant de 'réagir'; importer App de './app/components/App'; importer AppRegistry, View de 'react-native'; class RNAnimation étend Component render () return () AppRegistry.registerComponent ('RNAnimation', () => RNAnimation);
Si vous êtes sur React Native for Web, vous pouvez ignorer l’étape ci-dessus car le code par défaut est déjà configuré pour utiliser le programme. App
composant.
Créé un app / composants
dossier et à l'intérieur créer un App.js
fichier. Ce sera le fichier principal avec lequel nous allons travailler. Une fois le fichier créé, vous pouvez importer les packages dont vous aurez besoin pour l'ensemble du projet..
importer Réagir, Composant de 'réagir'; import Plate-forme, Feuille de style, Texte, ScrollView, Vue, Image, TouchableHighlight, Commutateur, Dimensions, Animé, Accélération, LayoutAnimation, UIManager à partir de 'react-native';
Si vous avez déjà effectué du développement React Native, vous devez déjà être familiarisé avec les composants suivants. Si ce n'est pas le cas, jetez un coup d'œil aux docs de React Native API.
Plate-forme, Feuille de style, Texte, ScrollView, Afficher, Image, TouchableHighlight, Switch, Dimensions,
Ce sont les packages spécifiquement utilisés pour l'implémentation d'animations:
Animation, Accélération, Mise en pageAnimation, UIManager
Voici un bref aperçu de chacun:
), texte (
) et des images (
).UIManager
.La première étape de la création d’une animation consiste à définir une valeur animée. Cela se fait généralement dans le constructeur du composant. Dans le code ci-dessous, nous définissons une nouvelle valeur animée pour le App
constructeur de composants. Notez que le nom de cette valeur peut être n'importe quoi dans la mesure où il décrit l'animation que vous souhaitez créer..
Dans React Native, vous pouvez créer une nouvelle valeur animée en appelant le Valeur()
méthode dans le Animé
classe. Puis fournissez la valeur animée initiale comme argument.
constructeur (accessoires) super (accessoires); this.spinValue = new Animated.Value (0);
Ensuite, créez la fonction qui exécutera l'animation de rotation.
Sur la première ligne, nous devons définir la valeur initiale de la valeur animée avec laquelle nous souhaitons travailler. Dans ce cas, on le met à 0.
Ensuite, nous créons une nouvelle animation de chronométrage en appelant le Animation.timing ()
une fonction. Ceci accepte la valeur animée actuelle comme premier argument et un objet contenant l'animation config comme second. L'objet doit contenir la valeur finale pour la valeur animée, la durée (en millisecondes) et le type d'animation d'accélération..
Enfin, appelez le début()
méthode pour démarrer l'animation.
spin () this.spinValue.setValue (0); Animation.timing (this.spinValue, toValue: 1, duration: 1500, easing: Easing.linear) .start ();
La dernière étape consiste à implémenter réellement l'animation. À l'intérieur de votre rendre()
méthode, définissez comment la valeur de rotation sera modifiée. Cela peut être fait en appelant le interpoler()
une fonction. Il accepte un objet contenant un plage d'entrée
et outputRange
. plage d'entrée
est un tableau contenant les valeurs de rotation initiale et finale. outputRange
est un tableau contenant les valeurs de rotation réelles.
Donc, initialement, l'objet à animer sera à une rotation de 0 degré et la valeur finale sera à 360 degrés. Cette rotation est effectuée sur une durée de 1 500 millisecondes, comme défini précédemment dans la configuration de l'animation..
const spin = this.spinValue.interpolate (inputRange: [0, 1], outputRange: ['0deg', '360deg']);
Lorsque vous rendez le composant, la valeur de rotation est ajoutée en tant que transformation dans les styles. Donc, si vous connaissez les animations CSS, il s’agit de la même implémentation dans React Native.
revenir ()
Maintenant que vous connaissez les bases de la création d'animations, créons-en quelques-unes afin que vous sachiez comment implémenter différents types. À l'intérieur de votre constructeur()
, créer un objet contenant les animations que nous allons implémenter:
var animations = [animation: 'spin', enabled: false, animation: 'scale', activé: false, animation: 'opacity', activé: false, animation: 'colorChange', activé: false , animation: 'parallelTranslateX', enabled: false];
Ne vous inquiétez pas si vous ne savez pas ce que chacun fait. Je vais vous expliquer tous. Pour le moment, tout ce que vous devez savoir, c'est que cette configuration indique si une animation est actuellement activée ou non. Une fois qu'il a été initialisé, ajoutez le des animations
tableau à l'état:
this.state = animations: animations;
Dans ton rendre()
fonction, ajoute les composants que nous allons animer ainsi que la liste des animations.
revenir () this.renderAnimationsList ()
le renderAnimationsList ()
fonction rend la liste des animations en utilisant Commutateur
et Texte
Composants.
renderAnimationsList () return this.state.animations.map ((item) => return () ); this.toggleAnimation (item.animation, valeur) style = styles.switch valeur = item.enabled /> item.animation
Commutateur
permet à l'utilisateur d'activer et de désactiver les animations. Chaque fois que l'utilisateur actionne le commutateur, le toggleAnimation ()
fonction est exécutée. Tout ce qu’il fait est de trouver l’animation en question et de mettre à jour la valeur de la activée
propriété à la valeur sélectionnée. Il met ensuite à jour l'état avec les valeurs mises à jour et parcourt toutes les animations, n'exécutant que celles activées..
toggleAnimation (animation, valeur) var animations = this.state.animations; var index = animations.findIndex ((obj) => return obj.animation == animation;); animations [index] .enabled = valeur; this.setState (animations: animations); animations.forEach ((item) => if (item.enabled) this [item.animation] (););
Ajoutez également les styles qui seront utilisés dans l'application.
const styles = StyleSheet.create (conteneur: flex: 1, alignItems: 'center', flexDirection: 'colonne', bouton: hauteur: 40, backgroundColor: '#eee', justificationContenu: 'centre', alignItems: 'center', marginTop: 10, item: flex: 2, flexDirection: 'row', hauteur: 50,, switch: marginBottom: 10, animation_type: marginLeft: 10, spinner: marginTop: 20 , alignSelf: 'center', largeur: 50, hauteur: 50, boîte: width: 50, hauteur: 50, zIndex: 100, red_box: backgroundColor: 'red', marginBottom: 20, blue_box: alignSelf : 'flex-start', backgroundColor: 'blue', green_box: alignSelf: 'flex-end', backgroundColor: 'green', squares_container: flexDirection: 'row', flex: 1, flexWrap: 'wrap' , carré: largeur: 35, hauteur: 35, couleur de fond: 'lightblue', marge: 10, nombre: fontSize: 20, fontWeight: 'bold');
L'animation d'échelle consiste à créer un objet plus grand ou plus petit que sa taille d'origine. Commencez par créer une nouvelle valeur animée dans le constructeur:
this.scaleValue = new Animated.Value (0);
Créez la fonction pour animer la balance. Cela ressemble à la tourner()
une fonction; la seule différence est la fonction d'accélération que nous utilisons. Ici nous utilisons easyOutBack
pour rendre la mise à l'échelle plus fluide. Ceci est utile surtout si cette animation est exécutée à plusieurs reprises. Si vous voulez savoir quelles autres fonctions d’assouplissement vous pouvez utiliser, consultez easings.net. Tous les assouplissements listés ici peuvent être utilisés dans React Native.
scale () this.scaleValue.setValue (0); Animated.timing (this.scaleValue, toValue: 1, duration: 1500, easing: Easing.easeOutBack) .start (() => if (this.state.animations [0] .enabled) this.scale ( ););
L’autre nouveauté de la fonction ci-dessus est que nous transmettons une fonction en tant qu’argument au début()
une fonction. Cette fonction est exécutée une fois l'animation terminée. Ici, nous vérifions si l'animation est activée, et si c'est le cas, nous appelons à nouveau la même fonction. Cela nous permet d'exécuter l'animation de manière répétée tant qu'elle est activée..
() => if (this.state.animations [0] .enabled) this.scale ();
Ensuite, dans ton rendre()
fonction, configurez l’interpolation de mise à l’échelle. Cette fois, nous avons trois valeurs pour la plage d’entrée et de sortie afin de créer un effet de pulsation, comme une pulsation. Cela nous permet de créer une animation d'échelle qui ne rende pas brusquement un objet plus gros ou plus petit. La plage de sortie la plus élevée est 7, de sorte que l'objet sera sept fois plus grand que sa taille d'origine.
const nearFar = this.scaleValue.interpolate (inputRange: [0, 0.5, 1], outputRange: [1, 7, 1]);
Pour économiser de l'espace, ajoutez simplement le échelle
transformer sur le même composant que nous avons utilisé plus tôt:
Avec ces deux transformations ajoutées, vous pouvez maintenant activer à la fois les effets spéciaux et les animations d'échelle pour les exécuter simultanément..
A présent, vous devriez avoir remarqué les modèles qui nous permettent de créer des animations. Beaucoup de code est répété lors d'animations. La meilleure pratique serait de créer des fonctions qui encapsulent du code répété, mais pour que les choses restent simples et faciles à comprendre, gardons le code brut pour le reste des animations..
Essayons maintenant d’animer l’opacité d’un composant. A présent, vous devriez être assez au courant de la destination de chaque morceau de code, je ne vais donc plus vous dire où vous allez les placer. Mais au cas où vous seriez confus, vous pouvez simplement regarder le code sur GitHub:
this.opacityValue = new Animated.Value (0);
Créez une fonction pour changer l'opacité. Lorsque vous modifiez l'opacité, une fonction d'accélération linéaire est la meilleure solution, car elle est la plus simple..
opacity () this.opacityValue.setValue (0); Animated.timing (this.opacityValue, toValue: 1, duration: 3000, easing: Easing.linear) .start (() => if (this.state.animations [2] .enabled) this.opacity ( ););
Modifiez l'opacité de visible à transparent, puis à nouveau visible en l'espace de trois secondes..
const opacity = this.opacityValue.interpolate (inputRange: [0, 0.5, 1], outputRange: [1, 0, 1]);
Créez un nouveau composant dont l'opacité sera contrôlée:
Essayons ensuite d’animer la couleur de fond d’un composant:
this.colorValue = new Animated.Value (0);
Cette fois, nous animons sur cinq secondes:
colorChange () this.colorValue.setValue (0); Animation.timing (this.colorValue, toValue: 100, duration: 5000). Start (() => if (this.state.animations [3] .enabled) this.colorChange (););
Nous avons trois couleurs pour travailler. La couleur initiale est jaune, puis après quelques secondes, elle devient complètement orange, puis rouge. Notez que les couleurs ne changeront pas brusquement. toutes les couleurs entre les couleurs que vous avez spécifiées seront également affichées. React Native calcule automatiquement les valeurs de couleur entre celles que vous avez spécifiées. Vous pouvez allonger la durée si vous voulez voir comment la couleur change avec le temps..
const colorAnimation = this.colorValue.interpolate (inputRange: [0, 50, 100], outputRange: ['yellow', 'orange', 'red']);
Tout comme l'opacité, la valeur interpolée est ajoutée en tant que style:
Vous pouvez dire que nous avons déjà exécuté des animations en parallèle. Mais ce n'est qu'un effet secondaire d'avoir différentes transformations attachées à un seul composant. Si vous voulez exécuter plusieurs animations en même temps, vous devez utiliser le parallèle()
fonction de l'API animée. Ceci accepte un tableau de fonctions d'animation à exécuter. Dans l'exemple ci-dessous, nous avons deux valeurs animées, une pour chaque composant que nous voulons animer..
this.blue_box_X = new Animated.Value (0); this.green_box_X = new Animated.Value (0);
Dans la fonction d'animation, nous définissons les valeurs animées initiales comme d'habitude. Mais en dessous, nous utilisons Animated.parallel ()
pour regrouper toutes les animations que nous voulons effectuer. Dans ce cas, nous n'avons que deux animations de minutage, qui s'exécutent pendant deux secondes. Notez également que nous n'appelons pas le début()
méthode sur chaque animation. Au lieu de cela, nous l'utilisons après avoir déclaré l'animation parallèle. Cela nous permet de démarrer les animations simultanément.
parallelTranslateX () this.blue_box_X.setValue (0); this.green_box_X.setValue (0); Animated.parallel ([Animated.timing (this.blue_box_X, toValue: 1, durée: 2000, easing: Easing.linear), Animated.timing (this.green_box_X, toValue: 1, durée: 2000, easing: Easing: Facilité .linear)]). start (() => if (this.state.animations [4] .enabled) this.parallelTranslateX (););
Pour que l’interpolation ait un sens, vérifiez d’abord le style que nous avons ajouté pour les deux zones précédentes:
blue_box: alignSelf: 'flex-start', backgroundColor: 'bleu', green_box: alignSelf: 'flex-end', backgroundColor: 'vert',
La boîte bleue est alignée en utilisant départ flexible
, ce qui signifie qu'il est aligné à gauche. La boîte verte est extrémité flexible
, qui est aligné à droite. (Du moins, c’est comme cela qu’ils fonctionnent si le conteneur a une flexDirection
de colonne
. Sinon, c'est une autre histoire.)
Grâce à cette connaissance, nous pouvons maintenant déplacer les boîtes n'importe où. Mais pour ce tutoriel, tout ce que nous voulons faire est de déplacer les cases à l'opposé de leurs positions initiales. Ainsi, la boîte bleue se déplace vers la droite et la boîte verte se déplace vers la gauche. C’est là que les données de dimension de l’appareil entrent en jeu. Nous utilisons le largeur
de l'appareil pour calculer la valeur d'interpolation finale de sorte que la boîte ne sortira pas des limites.
var width = Dimensions.get ('fenêtre');
Dans ce cas, on soustrait simplement 50
de la largeur de l'appareil pour rendre la boîte bleue aller à droite. Et pour la zone verte, nous convertissons la largeur de l’appareil en son équivalent négatif afin qu’elle se déplace vers la gauche. Vous vous demandez peut-être pourquoi 50? C’est parce que la taille de chaque case est 50
. La boîte sera toujours hors limites si nous ne soustrayons pas sa propre taille de la largeur de l'appareil.
const blue_box_translateX = this.blue_box_X.interpolate (inputRange: [0, 1], outputRange: [0, width - 50],); const green_box_translateX = this.green_box_X.interpolate (inputRange: [0, 1], outputRange: [0, -width + 50],);
Enfin, ajoutez les composants à animer. La transformation en question est translateX
, ce qui nous permet de changer la position d'un objet dans l'axe des X afin de le déplacer horizontalement.
Outre les animations parallèles, il existe également les animations de séquence et de décalage.
L'implémentation de celles-ci est similaire aux animations parallèles en ce sens qu'elles acceptent toutes un tableau d'animations à exécuter. Mais le facteur déterminant pour les animations de séquence est que les animations que vous avez fournies dans le tableau seront exécutées en séquence. Vous pouvez également ajouter des délais optionnels à chaque animation si vous le souhaitez..
D'autre part, une animation décalée est une combinaison d'animations parallèles et séquentielles. En effet, cela vous permet d'exécuter des animations à la fois en parallèle et en séquence. Voici un stylo qui montre des animations décalées.
Un autre outil fourni par React Native pour la mise en œuvre des animations est LayoutAnimation
. Cela vous permet d’animer des vues dans leurs nouvelles positions lors de la prochaine mise en page. Les modifications de mise en page se produisent généralement lorsque vous mettez à jour l'état. Cela se traduit par l'ajout, la mise à jour ou la suppression d'un composant de l'interface utilisateur spécifique.
Quand ces événements se produisent, LayoutAnimation
se charge de l'animation du composant concerné. Par exemple, dans une application de liste de tâches, lorsque vous ajoutez un nouvel élément de tâche, il ajoute automatiquement une animation printanière pour que le nouvel élément soit créé..
Ajoutons un LayoutAnimation
dans l'application évier de cuisine. Comme mentionné précédemment, vous devrez importer LayoutAnimation
, Plate-forme
, et UIManager
dans l'application. Ensuite, dans ton constructeur()
, ajouter le code pour activer LayoutAnimation
sur Android:
if (Platform.OS === 'android') UIManager.setLayoutAnimationEnabledExperimental (true);
(Sur iOS, LayoutAnimation
devrait fonctionner par défaut. Si vous utilisez React Native for Web, LayoutAnimation n'est pas pris en charge. Vous devez donc exporter l'application vers Android ou iOS et l'essayer à partir de là.)
Ensuite, juste en dessous de la ScrollView
qui contient la liste des animations, ajoutez un bouton pour générer des carrés qui seront affichés à l'écran:
Ajouter des carrés
En gros, cela va générer trois petits carrés chaque fois que l'utilisateur appuie sur le bouton Ajouter des carrés bouton.
Voici la fonction pour ajouter des carrés:
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var carrés = this.state.squares; this.setState (carrés: carrés + 3);
L'idée est d'appeler le LayoutAnimation.configureNext ()
avant de mettre à jour l'état. Cela accepte l'animation que vous souhaitez utiliser. Hors de la boîte, LayoutAnimation
vient avec trois préréglages: linéaire
, printemps
, et easyInEaseOut
. Celles-ci devraient fonctionner dans la plupart des cas, mais si vous devez personnaliser les animations, vous pouvez lire la documentation sur LayoutAnimation pour apprendre à créer votre propre.
À l'intérieur de rendre()
fonction, créer un pour
boucle qui rendra les carrés. Le nombre de carrés à générer dépend de la valeur actuelle de des carrés
dans l'état.
carrés var = []; pour (var i = 0; i < this.state.squares; i++) squares.push(this.renderSquare(i));
le renderSquare ()
fonction est celle qui rend réellement les carrés:
renderSquare (clé) return ()
L'API animée de React Native est très robuste et personnalisable, mais comme vous l'avez vu jusqu'à présent, cela présente l'inconvénient de devoir écrire beaucoup de code pour mettre en œuvre des animations très simples. Donc, dans cette dernière section, je vais vous présenter deux bibliothèques tierces qui vous permettront d'implémenter des animations communes avec moins de code.
Si vous créez une application qui doit animer des chiffres (par exemple, une application pour chronomètre ou compteur), vous pouvez utiliser la fonction intégrée. setInterval ()
fonction pour mettre à jour l'état sur un intervalle défini, puis implémenter vous-même les animations.
Ou, si vous le souhaitez, vous pouvez utiliser la bibliothèque de numéros Animate. Cela vous permet d'implémenter facilement des animations de numéro, telles que la personnalisation de la transition à chaque mise à jour du numéro. Vous pouvez l'installer avec la commande suivante:
npm installer react-native-animate-number --save
Une fois installé, importez-le dans votre application:
importer AnimateNumber à partir de 'react-native-animate-number';
Ensuite, utilisez-le comme composant:
Le code ci-dessus compte jusqu'à 100 à partir de 0.
Si vous souhaitez implémenter des animations générales telles que celles proposées par la bibliothèque animate.css, il existe une bibliothèque équivalente pour React Native, appelée Animatable. Vous pouvez l'installer avec la commande suivante:
npm install react-native-animatable --save
Une fois installé, importez-le avec le code suivant:
importer * comme animable à partir de 'react-native-animatable';
Voici un exemple utilisant le code que nous avons ajouté précédemment pour notre animation de présentation. Tout ce que vous avez à faire est d'utiliser
au lieu de
puis ajoutez un ref
afin que nous puissions faire référence à ce composant en utilisant du code JavaScript.
carrés
Ensuite, créez un resetSquares ()
méthode. Cela supprimera tous les carrés actuellement affichés à l'écran. Utilisation this.refs.squares
faire référence au conteneur de places, puis appeler le zoomOutUp ()
pour l’animer en utilisant une animation avec zoom arrière avec la direction vers le haut. Et n'oubliez pas de mettre à jour l'état une fois l'animation terminée. Ceci est un modèle commun lors de la mise en œuvre des animations. Faire l'animation avant de mettre à jour l'état.
resetSquares () this.refs.squares.zoomOutUp (1500) .then (() => this.setState (carrés: 0););
La même chose est vraie avec le addSquares ()
méthode. Mais cette fois, nous réanimons le conteneur de carrés. Et au lieu d'exécuter l'animation en premier, nous le faisons juste après la mise à jour de l'état. En effet, le conteneur de carrés n'est pas réellement affiché, sauf s'il a un enfant. Donc ici nous enfreignons la règle selon laquelle l'animation doit être exécutée en premier.
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var carrés = this.state.squares; if (carrés == 0) this.setState (carrés: carrés + 3, () => ceci.refs.squares.zoomInDown (1);); else this.setState (carrés: carrés + 3);
C'est tout! Dans cet article, vous avez appris les bases de la création d’animations dans React Native. Les animations peuvent être implémentées à l'aide de l'API animée, LayoutAnimations
, et bibliothèques tierces.
Comme vous l'avez vu, la création d'animations peut prendre une quantité considérable de code, même pour les plus simples telles qu'une animation de redimensionnement. Cela présente l'avantage de vous permettre de personnaliser les animations comme vous le souhaitez..
Toutefois, si vous ne souhaitez pas gérer trop de code, vous pouvez toujours utiliser des bibliothèques tierces React Native spécialement créées pour faciliter l'implémentation d'animations. Vous pouvez trouver le code source complet utilisé dans ce tutoriel sur GitHub.
Enfin, si vous souhaitez en savoir plus sur l’animation CSS, consultez certains de nos cours vidéo..