Animasjon er en viktig del av brukeropplevelsesdesign. Den tjener som tilbakemelding på brukerhandlinger, informerer brukere om systemstatus, og veileder dem om hvordan man kan interagere med grensesnittet.
Et av verktøyene jeg bruker til å lage mobilprogrammer på tversplattform, er React Native, så i denne opplæringen vil jeg gå gjennom hvordan du implementerer animasjoner i denne plattformen. Den endelige utgangen for denne opplæringen vil være en kjøkkenvask-app som implementerer ulike typer animasjoner. Slik ser det ut:
Jeg antar at du allerede vet grunnleggende om å jobbe med React Native, så jeg vil ikke være for mye i koden som ikke har noe å gjøre med animasjoner. For mer bakgrunn på React Native, sjekk ut noen av mine andre opplæringsprogrammer.
Vi vil være spesielt jobber på Android-plattformen, men koden som brukes i denne opplæringen, bør også fungere på iOS. Faktisk, hvis du ikke vil håndtere smerten ved å sette opp et nytt React Native-prosjekt, anbefaler jeg at du sjekker ut React Native Web Starter. Dette lar deg lage et nytt React Native-prosjekt som du kan forhåndsvise i nettleseren. Dette kommer med fordelen av at du ikke trenger å konfigurere en enhet, og raskere varmt lasting, slik at du kan forhåndsvise endringene raskere.
Hvis du ikke har gjort det allerede, opprett et nytt React Native-prosjekt:
reager-innfødt init RNAnimasjon
Hvis du bruker React Native Web Starter, kan du lage et nytt prosjekt:
git klone https://github.com/grabcode/react-native-web-starter.git RNAnimation cd RNAnimation rm -rf .git npm installere
Åpne index.android.js (eller index.web.js) -Filen, fjern standardkoden og legg til følgende:
Import React, Component fra 'reagere'; importer App fra './app/components/App'; importer AppRegistry, View fra 'react-native'; klasse RNAnimation utvider komponent render () return (); AppRegistry.registerComponent ('RNAnimation', () => RNAnimation);
Hvis du er på React Native for Web, kan du hoppe over trinnet ovenfor som standardkoden allerede er konfigurert for å bruke app
komponent.
Lag en app / komponenter
mappe og innsiden lage en App.js
fil. Dette blir den primære filen vi skal jobbe med. Når du har opprettet filen, kan du gå videre og importere pakkene du trenger for hele prosjektet.
Import React, Component fra 'reagere'; importere Platform, StyleSheet, Text, ScrollView, View, Image, TouchableHighlight, Switch, Dimensjoner, Animert, Easing, LayoutAnimation, UIManager fra 'reagere-native';
Hvis du har gjort noen form for React Native-utvikling før, bør du allerede være ganske kjent med følgende komponenter. Hvis ikke, ta en titt på React Native API-dokumentene.
Platform, StyleSheet, Text, ScrollView, View, Image, TouchableHighlight, Switch, Dimensjoner,
Dette er pakkene som er spesielt brukt for å implementere animasjoner:
Animert, Easing, LayoutAnimation, UIManager
Her er en kort oversikt over hver enkelt:
), tekst (
), og bilder (
).UIManager
.Det første trinnet i å lage en animasjon er å definere en animert verdi. Dette gjøres vanligvis innenfor komponentkonstruktoren. I koden nedenfor definerer vi en ny animert verdi for app
komponent konstruktør. Merk at navnet på denne verdien kan være alt så lenge det beskriver animasjonen du vil opprette.
I React Native kan du opprette en ny animert verdi ved å ringe Verdi()
metode i Animert
klasse. Deretter gir du den første animerte verdien som argumentet.
konstruktør (rekvisitter) super (rekvisitter); this.spinValue = new Animated.Value (0);
Deretter lager du funksjonen som vil utføre rotasjonsanimasjonen.
På den første linjen må vi sette innledningsverdien til den animerte verdien vi vil jobbe med. I dette tilfellet setter vi det til 0.
Deretter oppretter vi en ny timing animasjon ved å ringe Animated.timing ()
funksjon. Dette aksepterer den nåværende animerte verdien som sitt første argument og et objekt som inneholder animasjonskonfigurasjonen som sin andre. Objektet skal inneholde den endelige verdien for animasjonsverdien, varigheten (i millisekunder) og typen av lettelse-animasjon.
Til slutt, ring til start()
metode for å starte animasjonen.
spin () this.spinValue.setValue (0); Animated.timing (this.spinValue, toValue: 1, duration: 1500, easing: Easing.linear) .start ();
Det siste trinnet er å faktisk implementere animasjonen. Inne i din render ()
metode, definer hvordan rotasjonsverdien vil bli endret. Dette kan gjøres ved å ringe interpolere ()
funksjon. Den aksepterer et objekt som inneholder en inputRange
og outputRange
. inputRange
er en matrise som inneholder den opprinnelige og endelige rotasjonsverdien. outputRange
er en matrise som inneholder de faktiske rotasjonsverdiene.
Så først vil objektet som skal animeres, være 0 graders rotasjon, og den endelige verdien vil være 360 grader. Denne rotasjonen gjøres i løpet av 1500 millisekunder, som definert tidligere i animasjonskonfigurasjonen.
const spin = this.spinValue.interpolate (inputRange: [0, 1], outputRange: ['0deg', '360deg']);
Når du gjør komponenten, blir rotasjonsverdien lagt til som en transformasjon i stilene. Så hvis du er kjent med CSS-animasjoner, er dette tilsvarende implementering i React Native.
komme tilbake ();
Nå som du vet grunnleggende om å skape animasjoner, la oss lage noen få flere, slik at du vet hvordan du implementerer ulike typer. Inne i din konstruktør ()
, opprett et objekt som inneholder animasjonene som vi skal implementere:
Var animasjoner = [animasjon: 'spin', aktivert: false, animasjon: 'skala', aktivert: false, animasjon: 'opacity', aktivert: false, animasjon: 'colorChange' , animasjon: 'parallelTranslateX', aktivert: false];
Ikke bekymre deg hvis du ikke vet hva hver enkelt gjør - jeg kommer til å gå deg gjennom dem alle. Alt du trenger å vite for nå er at denne konfigurasjonen angir om en animasjon er aktivert eller ikke. Når det er blitt initialisert, legg til animasjoner
array til staten:
this.state = animasjoner: animasjoner;
I din render ()
funksjon, legg til komponentene som vi skal animere, samt listen over animasjoner.
komme tilbake (); This.renderAnimationsList ()
De renderAnimationsList ()
funksjonen gjør listen over animasjoner ved hjelp av Bytte om
og Tekst
komponenter.
renderAnimationsList () return this.state.animations.map ((item) => return (); ); this.toggleAnimation (item.animation, value) style = styles.switch verdi = item.enabled /> Item.animation
Bytte om
tillater brukeren å bytte animasjoner på og av. Hver gang brukeren slår på bryteren, toggleAnimation ()
funksjonen blir utført. Alt det gjør er å finne animasjonen i spørsmålet og oppdatere verdien av aktivert
eiendom til den valgte verdien. Den oppdaterer deretter staten med de oppdaterte verdiene og løkkene gjennom alle animasjonene, og utfører bare de aktiverte.
toggleAnimation (animasjon, verdi) var animations = this.state.animations; var index = animations.findIndex ((obj) => return obj.animation == animation;); animasjoner [index] .enabled = value; this.setState (animasjoner: animasjoner); animations.forEach ((item) => if (item.enabled) dette [item.animation] (););
Legg også til stilene som vil bli brukt i hele appen.
const styles = StyleSheet.create (container: flex: 1, alignItems: 'center', flexDirection: 'kolonne', knapp: høyde: 40, backgroundColor: '#eee', justifyContent: 'center', alignItems: 'senter', marginTop: 10, element: flex: 2, flexDirection: 'rad', høyde: 50,, bryter: marginBottom: 10, animation_type: marginLeft: 10, spinner: marginTop: 20 , alignSelf: 'senter', bredde: 50, høyde: 50, boks: bredde: 50, høyde: 50, zIndex: 100, red_box: backgroundColor: 'rød', marginBottom: 20, blue_box: alignSelf : 'flex-start', backgroundColor: 'blue', green_box: alignSelf: 'flex-end', backgroundColor: 'green', squares_container: flexDirection: 'row', flex: 1, flexWrap: 'wrap' , square: width: 35, height: 35, backgroundColor: 'lightblue', margin: 10, tall: fontSize: 20, fontWeight: 'bold');
Skala animasjon er hvor du lager et objekt større eller mindre enn den opprinnelige størrelsen. Begynn med å opprette en ny animert verdi inne i konstruktøren:
this.scaleValue = new Animated.Value (0);
Opprett funksjonen for å animere skalaen. Dette ligner på snurre rundt()
funksjon; Den eneste forskjellen er den lette funksjonen som vi bruker. Her bruker vi easeOutBack
for å gjøre skaleringen mer væsken. Dette er nyttig spesielt hvis denne animasjonen utføres gjentatte ganger. Hvis du vil vite hvilke andre lettelse funksjoner du kan bruke, sjekk ut easings.net. Alle de lettelser som er oppført der, kan brukes i React Native.
skala () this.scaleValue.setValue (0); Animated.timing (this.scaleValue, toValue: 1, duration: 1500, easing: Easing.easeOutBack) .start (() => hvis (this.state.animations [0] .enabled) this.scale ););
Den andre tingen som er ny i funksjonen ovenfor er at vi passerer i en funksjon som et argument til start()
funksjon. Denne funksjonen blir utført når animasjonen er ferdig. Her kontrollerer vi om animasjonen er aktivert, og hvis det er, kaller vi den samme funksjonen igjen. Dette tillater oss å utføre animasjonen gjentatte ganger så lenge den er aktivert.
() => hvis (this.state.animations [0] .enabled) this.scale ();
Så, i din render ()
funksjon, konfigurer skaleringsinterpoleringen. Denne gangen har vi tre verdier for inngangs- og utgangsområdet for å skape en pulserende effekt, som et hjerterytme. Dette gjør at vi kan lage en skala animasjon som ikke brått gjør et objekt større eller mindre. Det høyeste utdataområdet er 7, så objektet vil være syv ganger større enn dets opprinnelige størrelse.
const nearFar = this.scaleValue.interpolate (inputRange: [0, 0.5, 1], outputRange: [1, 7, 1]);
For å spare plass, legg bare til skala
forvandle på samme komponent som vi brukte tidligere:
Med disse to transformasjonene lagt til, kan du nå aktivere både rotasjons- og skalaanimasjonen for å utføre dem samtidig.
Nå bør du ha lagt merke til mønstrene som tillater oss å lage animasjoner. Massevis av kode gjentas når du gjør animasjoner. Beste praksis ville være å skape funksjoner som inkapsler gjentatt kode, men for å holde ting enkelt og lett å forstå, la oss holde fast med den røde koden for resten av animasjonene.
La oss nå prøve å animere opaciteten til en komponent. Nå skal du være ganske kjent med hvor hvert stykke kode går, så jeg skal ikke lenger nevne hvor du vil plassere hverandre. Men hvis du blir forvirret, kan du bare se på koden på GitHub:
this.opacityValue = new Animated.Value (0);
Lag en funksjon for å endre opasiteten. Når du endrer opaciteten, er en lineær lettelse-funksjon den beste passformen, siden det er den mest enkle.
opacity () this.opacityValue.setValue (0); Animated.timing (this.opacityValue, toValue: 1, duration: 3000, easing: Easing.linear) .start (() => hvis (this.state.animations [2] .enabled) this.opacity ););
Endre opasiteten fra synlig til gjennomsiktig og så synlig igjen i løpet av tre sekunder.
const opacity = this.opacityValue.interpolate (inputRange: [0, 0.5, 1], outputRange: [1, 0, 1]);
Opprett en ny komponent hvis opasitet skal kontrolleres:
Deretter skal vi prøve å animere bakgrunnsfargen til en komponent:
this.colorValue = new Animated.Value (0);
Denne gangen animerer vi i løpet av fem sekunder:
colorChange () this.colorValue.setValue (0); Animated.timing (this.colorValue, toValue: 100, duration: 5000). Start (() => hvis (this.state.animations [3] .enabled) this.colorChange (););
Vi har tre farger å jobbe med. Den innledende farge er gul, og etter noen sekunder blir den helt til oransje, og deretter til rød. Legg merke til at fargene ikke vil skifte skift; alle fargene mellom fargene du angav vil også bli vist. React Native beregner automatisk fargeverdiene mellom de som du angav. Du kan gjøre lengre varighet hvis du vil se hvordan fargen endres over tid.
const colorAnimation = this.colorValue.interpolate (inputRange: [0, 50, 100], outputRange: ['gul', 'oransje', 'rød']);
På samme måte som opaciteten blir den interpolerte verdien lagt til som en stil:
Du kan si at vi allerede har utført animasjoner parallelt. Men det er bare en bivirkning av å ha forskjellige transformasjoner festet til en enkelt komponent. Hvis du vil utføre flere animasjoner på samme tid, må du bruke parallell()
Funksjonen fra Animated API. Dette aksepterer en rekke animasjonsfunksjoner som skal utføres. I eksemplet nedenfor har vi to animerte verdier, en for hver komponent som vi ønsker å animere.
this.blue_box_X = new Animated.Value (0); this.green_box_X = new Animated.Value (0);
I animasjonsfunksjonen setter vi de første animerte verdiene som vanlig. Men under det bruker vi Animated.parallel ()
å gruppere alle animasjonene vi vil utføre. I dette tilfellet har vi bare to timing animasjoner, som utføres i to sekunder. Vær også oppmerksom på at vi ikke ringer til start()
metode på hver animasjon. I stedet bruker vi den etter å ha erklært parallell animasjon. Dette tillater oss å starte animasjonene samtidig.
parallelTranslateX () this.blue_box_X.setValue (0); this.green_box_X.setValue (0); Animated.parallel ([Animated.timing (this.blue_box_X, toValue: 1, duration: 2000, easing: Easing.linear), Animated.timing (this.green_box_X, toValue: 1, duration: 2000, easing: Easing .linear)]). start (() => hvis (this.state.animations [4] .enabled) this.parallelTranslateX (););
For at interpoleringen skal gi mening, må du først sjekke stilen som vi la til for de to boksene tidligere:
blue_box: alignSelf: 'flex-start', backgroundColor: 'blue', green_box: alignSelf: 'flex-end', backgroundColor: 'green',
Den blå boksen er justert med flex-start
, som betyr at den er justert til venstre. Den grønne boksen er flex-end
, som er justert til høyre. (Det er i hvert fall slik at de fungerer hvis containeren har en flexDirection
av kolonne
. Ellers er det en annen historie.)
Med denne kunnskapen kan vi nå flytte boksene hvor som helst vi vil. Men for denne opplæringen er alt vi ønsker å gjøre, å flytte boksene til motsatt av deres opprinnelige posisjoner. Så flyttes den blå boksen til høyre, og den grønne boksen beveger seg til venstre. Dette er hvor enhetens dimensjonsdata kommer inn. Vi bruker bredde
av enheten for å beregne den endelige interpoleringsverdien slik at boksen ikke vil gå ut av grensene.
var width = Dimensions.get ('window');
I dette tilfellet trekker vi ganske enkelt ut 50
fra enhetens bredde for å gjøre den blå boksen gå til høyre. Og for den grønne boksen konverterer vi enhetsbredden til den negative ekvivalenten, slik at den beveger seg til venstre. Du lurer kanskje på hvorfor 50? Dette skyldes at størrelsen på hver boks er 50
. Boksen vil fortsatt gå ut av grensen hvis vi ikke trekker sin egen størrelse fra enhetens bredde.
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, -bredde + 50],);
Til slutt, legg til komponentene som skal animeres. Omdanningen er spørsmålet translateX
, som tillater oss å endre posisjonen til et objekt i X-aksen for å flytte det horisontalt.
Bortsett fra parallelle animasjoner, er det også sekvensen og stagger animasjoner.
Implementeringen av disse ligner parallelle animasjoner i den forstand at de alle aksepterer en rekke animasjoner som skal utføres. Men den definerende faktoren for sekvensanimasjoner er at animasjonene du har levert i arrayet, vil bli utført i rekkefølge. Du kan også legge til valgfrie forsinkelser for hver animasjon hvis du vil.
På den annen side er en stagger animasjon en kombinasjon av parallelle og sekvens animasjoner. Dette er fordi det lar deg kjøre animasjoner både parallelt og i rekkefølge. Her er en penn som viser stagger animasjoner.
Et annet verktøy som React Native sørger for å implementere animasjoner er LayoutAnimation
. Dette lar deg animere visninger til deres nye stillinger når neste layout skjer. Oppsettendringer skjer vanligvis når du oppdaterer staten. Dette resulterer i at en bestemt brukergrensesnittkomponent enten legges til, oppdateres eller fjernes fra skjermen.
Når disse hendelsene skjer, LayoutAnimation
tar seg av å animere komponenten. Hvis du for eksempel legger til en ny oppgave, vil den automatisk legge til en fjæranimasjon for å få det nye elementet til å eksistere i en gjøremålsliste-app..
La oss legge til en LayoutAnimation
inn i kjøkkenvasken app. Som nevnt tidligere må du importere LayoutAnimation
, Plattform
, og UIManager
inn i appen. Så, i din konstruktør ()
, legg til koden for å aktivere LayoutAnimation
på Android:
hvis (Platform.OS === 'android') UIManager.setLayoutAnimationEnabledExperimental (true);
(På iOS, LayoutAnimation
skal fungere som standard. Hvis du bruker React Native for Web, støttes LayoutAimimation ikke, så du må få appen eksportert til enten Android eller iOS, og prøv det derfra.)
Deretter rett under ScrollView
som inneholder animasjonslisten, legg til en knapp for å generere firkanter som vil bli vist på skjermen:
Legg til firkanter
I utgangspunktet hva dette vil gjøre er å generere tre små firkanter hver gang brukeren kraner på Legg til firkanter knapp.
Her er funksjonen for å legge til firkanter:
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var firkanter = this.state.squares; this.setState (kvadrater: kvadrater + 3);
Tanken er å ringe LayoutAnimation.configureNext ()
før du oppdaterer staten. Dette aksepterer animasjonen du vil bruke. Ut av boksen, LayoutAnimation
leveres med tre forhåndsinnstillinger: lineær
, vår
, og easeInEaseOut
. Disse skal fungere for de fleste tilfeller, men hvis du trenger å tilpasse animasjonene, kan du lese dokumentasjonen på LayoutAnimation for å lære å lage din egen.
Inne i render ()
funksjon, opprett en til
sløyfe som vil gjøre firkantene. Antall kvadrater som skal genereres avhenger av gjeldende verdi av torg
i tilstanden.
var firkanter = []; for (var i = 0; i < this.state.squares; i++) squares.push(this.renderSquare(i));
De renderSquare ()
funksjonen er den som faktisk gjør firkantene:
renderSquare (nøkkel) return ();
React Native's Animated API er veldig robust og tilpassbar, men som du har sett så langt, kommer dette med ulempen ved å skrive mye kode bare for å implementere veldig enkle animasjoner. Så i denne siste delen vil jeg introdusere deg til to tredjepartsbiblioteker som lar deg implementere vanlige animasjoner med mindre kode.
Hvis du oppretter en app som trenger å animere tall (for eksempel en stoppeklokke eller tellerapp), kan du bruke den innebygde setInterval ()
fungere for å oppdatere staten på et angitt intervall og deretter implementere animasjonene selv.
Eller hvis du vil, kan du bruke Animasjonsnummer-biblioteket. Dette gjør at du enkelt kan implementere antall animasjoner, for eksempel tilpasse overgangen hver gang nummeret oppdateres. Du kan installere den med følgende kommando:
npm installere reager-native-animert-nummer - lagre
Når du er installert, importerer du den til appen din:
importer AnimateNumber fra 'react-native-animate-number';
Bruk deretter den som en komponent:
Hva ovenfor koden gjør er teller opp til 100 fra 0.
Hvis du vil implementere generelle formål animasjoner som de som tilbys av animate.css biblioteket, er det et tilsvarende bibliotek for React Native kalt Animatable. Du kan installere den med følgende kommando:
npm installere reager-native-animatable - save
Når du er installert, importerer du den med følgende kode:
importer * som animatable fra 'reagere-native-animatable';
Her er et eksempel ved å bruke koden som vi la til tidligere for vår layout animasjon. Alt du trenger å gjøre er å bruke
i stedet for
og legg deretter til en ref
så vi kan referere til denne komponenten ved hjelp av JavaScript-kode.
kvadrater
Deretter oppretter du en resetSquares ()
metode. Dette fjerner alle rutene som er på skjermen. Bruk this.refs.squares
å referere til torgets container, og ring deretter zoomOutUp ()
funksjon for å animere den ut av visningen ved hjelp av en zoom ut animasjon med opp retning. Og ikke glem å oppdatere staten etter at animasjonen har fullført. Dette er et vanlig mønster når du implementerer animasjoner. Gjør animasjonen før du oppdaterer staten.
resetSquares () this.refs.squares.zoomOutUp (1500) .then (() => this.setState (kvadrater: 0););
Det samme gjelder for addSquares ()
metode. Men denne gangen animerer vi firkantbeholderen inn igjen. Og i stedet for å utføre animasjonen først, gjør vi det rett etter at staten har blitt oppdatert. Dette skyldes at firkantbeholderen egentlig ikke vises, med mindre barnet har det. Så her bryter vi regelen om at animasjonen skal utføres først.
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var firkanter = this.state.squares; hvis (firkanter == 0) this.setState (kvadrater: kvadrater + 3, () => this.refs.squares.zoomInDown (1);); annet this.setState (kvadrater: kvadrater + 3);
Det er det! I denne artikkelen har du lært grunnleggende om å lage animasjoner i React Native. Animasjoner kan implementeres ved hjelp av animert API, LayoutAnimations
, og tredjepartsbiblioteker.
Som du har sett, kan skape animasjoner ta en betydelig mengde kode, selv for enkle som en skaleringsanimasjon. Dette kommer med fordelen av at du kan tilpasse animasjonene som du vil.
Men hvis du ikke vil håndtere for mye kode, kan du alltid bruke tredjeparts React native biblioteker som er spesielt opprettet for å enkelt implementere animasjoner. Du finner full kildekoden som brukes i denne opplæringen på GitHub.
Til slutt, hvis du vil lære mer om CSS animasjon, sjekk ut noen av våre videokurser.