Animația este o parte importantă a designului experienței utilizatorului. Acesta servește drept feedback privind acțiunile utilizatorilor, informează utilizatorii despre starea sistemului și îi îndrumă asupra interacțiunii cu interfața.
Unul dintre instrumentele pe care le folosesc pentru a crea aplicații mobile pe mai multe platforme este React Native, așa că în acest tutorial vă voi învăța cum să implementați animații pe această platformă. Rezultatul final pentru acest tutorial va fi o aplicație pentru chiuveta de bucătărie care implementează diferite tipuri de animații. Iată cum va arăta:
Voi presupune că deja cunoașteți elementele de bază ale colaborării cu React Native, așa că nu voi fi delveat prea mult în codul care nu are nimic de-a face cu animațiile. Pentru mai multe informații despre React Native, consultați câteva din celelalte tutoriale ale mele.
Vom lucra în mod special pe platforma Android, dar codul folosit în acest tutorial ar trebui să funcționeze și pe iOS. De fapt, dacă nu doriți să faceți față cu durerea înființării unui nou proiect React Native, vă recomandăm să verificați Reactiva Nativă Web Starter. Acest lucru vă permite să creați un nou proiect React Native pe care îl puteți previzualiza în browser. Acest lucru vine cu avantajul de a nu fi nevoie să configurați un dispozitiv și de reîncărcarea rapidă la cald, pentru a vă putea previzualiza modificările mai rapid.
Dacă nu ați făcut deja acest lucru, creați un nou proiect React Native:
reactiv-nativ init RNAimation
Dacă utilizați React Nativ Web Starter, iată cum creați un nou proiect:
git clone https://github.com/grabcode/react-native-web-starter.git RNAimilare cd RNAimation rm -rf .git npm install
Deschide index.android.js (sau index.web.js), Eliminați codul implicit și adăugați următoarele:
import React, Component de la "reacție"; import App din "./app/components/App"; import AppRegistry, View de la "reactive-native"; clasa RNAnimation extinde Component render () return (); AppRegistry.registerComponent ("RNAimation", () => RNAimation);
Dacă sunteți în React Nativ pentru Web, puteți trece peste pasul de mai sus, deoarece codul implicit este deja setat pentru a utiliza App
component.
Creaza un app / componente
dosarul și interiorul crea un App.js
fişier. Acesta va fi fișierul primar cu care vom lucra. Odată ce ați creat fișierul, puteți continua și puteți importa pachetele de care aveți nevoie pentru întregul proiect.
import React, Component de la "reacție"; importați Platform, StyleSheet, Text, ScrollView, Vizualizare, Imagine, TouchableHighlight, Switch, Dimensiuni, animate, Easing, LayoutAnimation, UIManager de la "reactive-native";
Dacă ați făcut vreun fel de dezvoltare Nativă React înainte, ar trebui să fiți deja destul de familiarizați cu următoarele componente. Dacă nu, aruncați o privire la documentele React Native API.
Platformă, StyleSheet, Text, ScrollView, Vizualizare, Imagine, TouchableHighlight, Switch, Dimensiuni,
Acestea sunt pachetele care sunt utilizate în mod specific pentru implementarea animațiilor:
Animat, relaxare, dispunere animație, UIManager
Iată o scurtă trecere în revistă a fiecăruia:
), text (
) și imagini (
).UIManager
.Primul pas în crearea unei animații este definirea unei valori animate. Acest lucru se face în interiorul constructorului componentelor. În codul de mai jos, definim o nouă valoare animată pentru App
constructor de componente. Rețineți că numele acestei valori poate fi orice, atâta timp cât descrie animația pe care doriți să o creați.
În Reacție Nativă, puteți crea o nouă valoare animată prin apelarea Valoare()
metodă în Animat
clasă. Apoi furnizați valoarea animată inițială ca argument.
constructor (recuzită) super (recuzită); this.spinValue = nou Animated.Value (0);
Apoi, creați funcția care va executa animația de rotire.
Pe prima linie, trebuie să setăm valoarea inițială a valorii animate cu care vrem să lucrăm. În acest caz, îl setăm la 0.
Apoi, vom crea o nouă animație de sincronizare sunând la Animated.timing ()
funcţie. Aceasta acceptă valoarea animată curentă drept primul argument și un obiect care conține configurația de animație ca fiind a doua. Obiectul trebuie să conțină valoarea finală pentru valoarea animată, durata (în milisecunde) și tipul de animație relaxantă.
În cele din urmă, apelați start()
metodă pentru a începe animația.
rotație () this.spinValue.setValue (0); Animated.timing (aceasta.spinValue, toValue: 1, durata: 1500, relaxare: Easing.linear) .start ();
Ultimul pas este de a implementa animația. În interiorul tău face()
, definiți modul în care va fi schimbată valoarea rotației. Acest lucru se poate face apelând interpola()
funcţie. Acceptă un obiect care conține un inputRange
și outputRange
. inputRange
este o matrice care conține valoarea de rotație inițială și finală. outputRange
este o matrice care conține valorile efective de rotație.
Deci, inițial, obiectul care urmează să fie animat va fi la 0 grade rotație, iar valoarea finală va fi de 360 de grade. Această rotire se face pe parcursul a 1500 de milisecunde, așa cum este definit mai devreme în config-ul de animație.
const spin = acest.spinValue.interpolate (inputRange: [0, 1], outputRange: ['0deg', '360deg']);
Când faceți componenta, valoarea rotației este adăugată ca o transformare în stiluri. Deci, dacă sunteți familiarizat cu animațiile CSS, aceasta este implementarea echivalentă în React Native.
întoarcere ();
Acum, că știți elementele de bază ale creării de animații, să creăm câteva mai multe, astfel încât să știți cum să implementați diferite tipuri. În interiorul tău constructor()
, creați un obiect care conține animațiile pe care le vom implementa:
var animations = [animație: 'spin', activat: false, animație: 'scară', activat: false, animație: opacitate '; , animație: 'parallelTranslateX', activat: false];
Nu vă faceți griji dacă nu știți ce face fiecare dintre voi - vă voi trece prin toate. Tot ce trebuie să știți pentru moment este că această configurație afișează dacă o animație este activată sau nu. După ce a fost inițializată, adăugați animații
array la stat:
this.state = animații: animații;
În tine face()
adăugați componentele pe care le animăm, precum și lista de animații.
întoarcere (); This.renderAnimationsList ()
renderAnimationsList ()
funcția redă lista de animații folosind Intrerupator
și Text
componente.
renderAnimationsList () returnați acest.state.animations.map ((item) => return (); ); this.toggleAnimație (element.animare, valoare) style = styles.switch value = item.enabled /> Item.animation
Intrerupator
permite utilizatorului să activeze și să dezactiveze animațiile. De fiecare dată când utilizatorul învârte comutatorul, toggleAnimation ()
funcția este executată. Tot ce face este să găsească animația în cauză și să actualizeze valoarea activat
proprietate la valoarea selectată. Apoi actualizează starea cu valorile și buclele actualizate prin toate animațiile, executând numai cele activate.
toggleAnimation (animație, valoare) var animations = this.state.animations; var index = animații.findIndex ((obj) => return obj.animation == animație;); animații [index] .enabled = valoare; this.setState (animații: animații); animations.forEach ((item) => if (item.enabled) this [item.animation] (););
Adăugați, de asemenea, stilurile care vor fi utilizate în întreaga aplicație.
const stiles = StyleSheet.create (container: flex: 1, alignItems: 'centru', flexDirection: 'columna, butonul: height: 40, backgroundColor:' #eee ', justifyContent: 'center', marginTop: 10, element: flex: 2, flexDirection: 'rând', înălțime: 50, comutator: marginBottom: 10, animation_type: marginLeft: 10, spinner: marginTop: , alignSelf: 'centru', lățime: 50, înălțime: 50, cutie: lățime: 50, înălțime: 50, zIndex: 100, red_box: backgroundColor: 'red', marginBottom: 20, blue_box: alignSelf : flex-start, fundalColor: 'albastru', verde_box: alignSelf: flex-end, fundalColor: verde, squares_container: flexDirection: , pătrat: lățime: 35, înălțime: 35, fundalColor: "lumină deschisă", margine: 10, număr: fontSize: 20, fontWeight: 'bold');
Scala de animație este locul în care faceți un obiect mai mare sau mai mic decât dimensiunea originală. Începeți prin crearea unei noi valori animate în interiorul constructorului:
this.scaleValue = noua valoare animat.value (0);
Creați funcția pentru animarea scalei. Acest lucru arată similar cu a invarti()
funcţie; singura diferență este funcția de relaxare pe care o folosim. Aici folosim easeOutBack
pentru a face scalarea mai fluidă. Acest lucru este util mai ales dacă această animație este executată în mod repetat. Dacă doriți să aflați ce alte funcții de relaxare puteți utiliza, consultați easings.net. Toate opiniile enumerate aici pot fi folosite în React Native.
scalare () this.scaleValue.setValue (0); Animate.timing (aceasta.scaleValue, toValue: 1, durata: 1500, relaxare: Easing.easeOutBack) .start (() => if (this.state.animations [0] .enabled) this.scale ););
Celălalt lucru nou în funcția de mai sus este că noi trecem într-o funcție ca un argument pentru start()
funcţie. Această funcție este executată când animația este terminată. Aici verificăm dacă animația este activată și, dacă este, apelăm din nou aceeași funcție. Acest lucru ne permite să executăm în mod repetat animația atâta timp cât este activată.
() => dacă (this.state.animations [0] .enabled) this.scale ();
Apoi, în tine face()
, configurați interpolarea de scalare. De data aceasta, avem trei valori pentru domeniul de intrare și ieșire pentru a crea un efect de pulsare, cum ar fi o bătăi de inimă. Acest lucru ne permite să creați o animație la scară care să nu facă brusc un obiect mai mare sau mai mic. Cel mai mare interval de ieșire este de 7, deci obiectul va fi de șapte ori mai mare decât dimensiunea originală.
const (= 0, 0.5, 1], outputRange: [1, 7, 1]);
Pentru a conserva spațiul, trebuie doar să adăugați scară
transformați pe aceeași componentă pe care am folosit-o mai devreme:
Cu cele două transformări adăugate, puteți acum să activați atât animația de spin, cât și animația pentru a le executa simultan.
Până acum ar fi trebuit să observi tiparele care ne permit să creăm animații. Multe coduri se repetă atunci când faci animații. Cea mai bună practică ar fi aceea de a crea funcții care încapsulează cod repetat, dar pentru a păstra lucrurile simple și ușor de înțeles, să rămânem cu codul brut pentru restul animațiilor.
Acum, să încercăm să animăm opacitatea unei componente. Până acum ar trebui să fii destul de familiarizat cu locul în care se află fiecare bucată de cod, așa că nu mai am de gând să menționez unde îi vei plasa pe fiecare. Dar, dacă vă confundați, puteți să vă uitați la codul de pe GitHub:
this.opacityValue = valoare animată nouă (0);
Creați o funcție pentru modificarea opacității. Când se schimbă opacitatea, funcția de relaxare liniară este cea mai potrivită deoarece este cea mai simplă.
opacitate () this.opacityValue.setValue (0); Animated.timing (aceasta.opacitateValue, toValue: 1, durata: 3000, relaxare: Easing.linear) .start (() => if (this.state.animations [2] .activat) this.opacity ););
Modificați opacitatea de la vizibil la transparent și apoi vizibilă din nou în decurs de trei secunde.
const opacity = this.opacityValue.interpolate (inputRange: [0, 0.5, 1], outputRange: [1, 0, 1]);
Creați o componentă nouă a cărei opacitate va fi controlată:
În continuare, să încercăm să animăm culoarea de fundal a unei componente:
this.colorValue = valoare animată nouă (0);
De data aceasta, animăm în cursul a cinci secunde:
colorChange () this.colorValue.setValue (0); Animated.timing (this.colorValue, toValue: 100, duration: 5000) start (() => if (this.state.animations [3] .activat) this.colorChange (););
Avem trei culori cu care să lucrăm. Culoarea inițială este galbenă și, după câteva secunde, se va transforma complet în portocaliu și apoi în roșu. Rețineți că culorile nu se vor schimba brusc; vor fi afișate toate culorile dintre culorile pe care le-ați specificat. Reactiva Native calculează automat valorile de culoare dintre cele pe care le-ați specificat. Puteți face o durată mai lungă dacă doriți să vedeți cum se schimbă culoarea în timp.
const culoareAnimație = this.colorValue.interpolate (inputRange: [0, 50, 100], outputRange: ['galben', 'portocaliu', 'roșu']);
La fel ca opacitatea, valoarea interpolată este adăugată ca un stil:
Puteți spune că am executat deja animații în paralel. Dar acesta este doar un efect secundar al transformărilor diferite atașate la o singură componentă. Dacă doriți să executați mai multe animații în același timp, trebuie să utilizați paralel()
funcția de la API animat. Aceasta acceptă o serie de funcții de animație care trebuie executate. În exemplul de mai jos, avem două valori animate, una pentru fiecare componentă pe care dorim să o animăm.
this.blue_box_X = noua valoare animată.Value (0); this.green_box_X = noua valoare animată.Value (0);
În funcția de animație, setăm valorile inițiale inițiale, ca de obicei. Dar sub ea, noi folosim Animated.parallel ()
pentru a grupa toate animațiile pe care vrem să le realizăm. În acest caz, avem doar două animații de sincronizare, care se execută timp de două secunde. De asemenea, observați că nu sunăm start()
pe fiecare animație. În schimb, îl folosim după declararea animației paralele. Acest lucru ne permite să pornim simultan animațiile.
paralelTranslateX () this.blue_box_X.setValue (0); this.green_box_X.setValue (0); Animated.parallel ([Animated.timing (this.blue_box_X, toValue: 1, duration: 2000, relaxing: Easing.linear), animated.timing (this.green_box_X, toValue: 1, duration: 2000, relaxing: () () () () () () () () ().
Pentru ca interpolarea să aibă sens, mai întâi verificați stilul pe care l-am adăugat pentru cele două cutii mai devreme:
blue_box: alignSelf: 'flex-start', fundalColor: 'albastru', green_box: alignSelf: 'flex-end', fundalColor: 'verde',
Cutia albastră este aliniată folosind flex-start
, ceea ce înseamnă că este aliniat la stânga. Cutia verde este flex-end
, care este aliniat la dreapta. (Cel puțin așa funcționează dacă containerul are a flexDirection
de coloană
. În caz contrar, este o poveste diferită.)
Cu aceste cunoștințe, acum putem muta cutiile oriunde vrem. Dar pentru acest tutorial, tot ce vrem să facem este să mutăm cutiile în opusul pozițiilor lor inițiale. Deci, cutia albastră se mișcă spre dreapta și cutia verde se mișcă spre stânga. Aici intră datele privind dimensiunile dispozitivului. Folosim lăţime
a dispozitivului pentru a calcula valoarea de interpolare finală astfel încât caseta să nu iasă din limite.
var width = Dimensions.get ("fereastră");
În acest caz, pur și simplu scădem 50
din lățimea dispozitivului pentru a face caseta albastră să meargă spre dreapta. Și pentru caseta verde, convertim lățimea dispozitivului la echivalentul său negativ, așa că se mișcă spre stânga. S-ar putea să te întrebi de ce 50? Acest lucru se datorează faptului că dimensiunea fiecărei cutii este 50
. Caseta va ieși din limite dacă nu scădem dimensiunea proprie din lățimea dispozitivului.
const blue_box_translateX = this.blue_box_X.interpolate (inputRange: [0, 1], outputRange: [0, lățimea - 50],); const: green_box_translateX = this.green_box_X.interpolate (inputRange: [0, 1], outputRange: [0, -width + 50],);
În cele din urmă, adăugați componentele care urmează să fie animate. Transformarea în cauză este translateX
, care ne permite să schimbăm poziția unui obiect în axa X pentru ao mișca orizontal.
În afară de animațiile paralele, există, de asemenea, animații secvență și animații.
Implementarea acestora este similară cu animațiile paralele, în sensul că acceptă cu toții o serie de animații care trebuie executate. Dar factorul definitoriu pentru animațiile de secvență este acela că animațiile pe care le-ați furnizat în matrice vor fi executate în ordine. De asemenea, puteți adăuga întârzieri opționale la fiecare animație dacă doriți.
Pe de altă parte, o animație eșalonată este o combinație de animații paralele și de secvențe. Acest lucru se datorează faptului că vă permite să rulați animații atât în paralel cât și în ordine. Iată un stilou care demonstrează animațiile de ștergere.
Un alt instrument pe care React Native îl oferă pentru implementarea animațiilor este LayoutAnimation
. Acest lucru vă permite să animați vederi în noile lor poziții atunci când se întâmplă aspectul următor. Schimbările de aspect se întâmplă de obicei atunci când actualizați starea. Acest lucru duce la adăugarea, actualizarea sau eliminarea unei componente UI specifice de pe ecran.
Când se întâmplă aceste evenimente, LayoutAnimation
are grijă de animarea componentei în cauză. De exemplu, într-o listă de liste de sarcini, atunci când adăugați un nou element de rezolvat, acesta va adăuga automat o animație de primăvară pentru a lansa noul element în existență.
Să adăugăm a LayoutAnimation
în chiuveta de bucătărie. Așa cum am menționat mai devreme, va trebui să importați LayoutAnimation
, Platformă
, și UIManager
în aplicație. Apoi, în tine constructor()
, adăugați codul pentru activare LayoutAnimation
pe Android:
dacă (Platform.OS === 'android') UIManager.setLayoutAnimationEnabledExperimental (adevărat);
(Pe iOS, LayoutAnimation
ar trebui să lucreze în mod implicit. Dacă utilizați React Native pentru Web, LayoutAnimation nu este acceptat, deci va trebui ca aplicația să fie exportată fie la Android, fie la iOS și să o încercați de acolo.)
Apoi, chiar sub ScrollView
care conține lista de animații, adăugați un buton pentru generarea de pătrate care vor fi afișate pe ecran:
Adăugați măturări
În principiu, ceea ce va face acest lucru este de a genera trei pătrate mici de fiecare dată când utilizatorul interceptează pe Adăugați măturări buton.
Iată funcția de adăugare a pătratelor:
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var pătrate = this.state.squares; acest setState (pătrate: pătrate + 3);
Ideea este de a apela LayoutAnimation.configureNext ()
înainte de a actualiza starea. Aceasta acceptă animația pe care doriți să o utilizați. Afara din cutie, LayoutAnimation
vine cu trei presetări: liniar
, primăvară
, și easeInEaseOut
. Acestea ar trebui să funcționeze în majoritatea cazurilor, dar dacă aveți nevoie să personalizați animațiile, puteți citi documentația despre LayoutAnimation pentru a afla cum să vă creați propriile.
În interiorul face()
funcția, creați o pentru
care va face patratele. Numărul de pătrate care urmează a fi generat depinde de valoarea curentă de pătrate
în statul.
var pătrate = []; pentru (var i = 0; i < this.state.squares; i++) squares.push(this.renderSquare(i));
renderSquare ()
funcția este cea care face efectiv patratele:
renderSquare (cheie) return ();
Reacționează că API-ul animat Native este foarte robust și personalizabil, dar așa cum ați văzut până acum, aceasta are dezavantajul că trebuie să scrieți o mulțime de cod doar pentru a implementa animații foarte simple. Deci, în această secțiune finală, vă voi prezenta două biblioteci terțe părți care vă vor permite să implementați animații comune cu mai puțin cod.
Dacă creați o aplicație care necesită animarea numerelor (de exemplu, un cronometru sau o aplicație pentru contor), puteți utiliza modulul încorporat setInterval ()
pentru a actualiza starea într-un interval setat și apoi pentru a implementa animațiile.
Sau dacă doriți, puteți utiliza biblioteca de numere de animație. Acest lucru vă permite să implementați cu ușurință animații cu numere, cum ar fi personalizarea tranziției de fiecare dată când numărul este actualizat. Puteți să o instalați cu următoarea comandă:
npm instalează rea-nativ-animate-number - salvează
Odată instalat, importați-l în aplicația dvs.:
import AnimateNumber din "reactiv-nativ-animate-number";
Apoi utilizați-o ca o componentă:
Ceea ce face codul de mai sus este numărul de până la 100 începând de la 0.
Dacă doriți să implementați animații cu scop general, cum ar fi cele oferite de biblioteca animate.css, există o bibliotecă echivalentă pentru React Native numită Animatable. Puteți să o instalați cu următoarea comandă:
npm instalează reactiv-nativ-animat - salvează
Odată instalat, importați-l cu următorul cod:
import * ca Animat de la "reactiv-nativ-animatable";
Iată un exemplu folosind codul pe care l-am adăugat mai devreme pentru animația noastră de layout. Tot ce trebuie să faceți este să folosiți
in loc de
și apoi adăugați o ref
astfel încât să putem face referire la această componentă folosind codul JavaScript.
pătrate
Apoi, creați un resetSquares ()
metodă. Aceasta va elimina toate pătratele care sunt în prezent pe ecran. Utilizare this.refs.squares
pentru a vă referi la containerul pătratelor și apoi apelați zoomOutUp ()
funcția de a anima afară din vedere folosind o zoom out animație cu direcția în sus. Și nu uitați să actualizați starea după terminarea animației. Acesta este un model comun atunci când se implementează animații. Faceți animația înainte de a actualiza starea.
resetSquares () this.refs.squares.zoomOutUp (1500) .then (() => this.setState (pătrate: 0););
Același lucru este valabil și pentru addSquares ()
metodă. Dar de data aceasta animăm containerul cu pătrate. Și în loc să executăm prima animație, o facem imediat după ce statul a fost actualizat. Acest lucru se datorează faptului că containerul cu pătrate nu este afișat cu adevărat decât dacă are un copil. Deci, aici încălcăm regula că animația ar trebui executată mai întâi.
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var pătrate = this.state.squares; dacă (pătrate == 0) this.setState (pătrate: pătrate + 3, () => this.refs.squares.zoomInDown (1);); altceva this.setState (squares: squares + 3);
Asta e! În acest articol, ați învățat elementele de bază ale creării de animații în React Native. Animațiile pot fi implementate utilizând API animat, LayoutAnimations
, și bibliotecile terților.
După cum ați văzut, crearea de animații poate lua o cantitate considerabilă de cod, chiar și pentru cele simple, cum ar fi o animație de scalare. Acest lucru vine cu avantajul de a vă permite să personalizați animațiile în orice fel doriți.
Cu toate acestea, dacă nu doriți să vă ocupați de prea mult cod, puteți utiliza întotdeauna biblioteci Reactive Native ale unor terțe părți create special pentru implementarea ușoară a animațiilor. Puteți găsi codul sursă complet folosit în acest tutorial pe GitHub.
În cele din urmă, dacă doriți să aflați mai multe despre animația CSS, consultați câteva dintre cursurile noastre video.