Animatie is een belangrijk onderdeel van het ontwerpen van gebruikerservaringen. Het dient als feedback op gebruikersacties, informeert gebruikers over de systeemstatus en begeleidt hen bij het omgaan met de interface.
Een van de tools die ik gebruik om platformonafhankelijke mobiele apps te maken is React Native, dus in deze tutorial zal ik je helpen met het implementeren van animaties in dit platform. De laatste uitvoer voor deze zelfstudie is een gootsteenapp die verschillende soorten animaties implementeert. Zo ziet het eruit:
Ik ga ervan uit dat je de basiskennis van werken met React Native al kent, dus ik zal me niet te veel in de code verdiepen die niets met animatie te maken heeft. Voor meer achtergrondinformatie over React Native, bekijk enkele van mijn andere tutorials.
We zullen specifiek aan het Android-platform werken, maar de code die in deze tutorial wordt gebruikt zou ook op iOS moeten werken. Als je de pijn van het opzetten van een nieuw React Native-project niet wilt aanpakken, raad ik aan om React Native Web Starter te bekijken. Hiermee kunt u een nieuw React Native-project maken dat u in de browser kunt bekijken. Dit heeft het voordeel dat u geen apparaat hoeft in te stellen en sneller opnieuw hoeft te laden, zodat u uw wijzigingen sneller kunt bekijken.
Als u dit nog niet hebt gedaan, maakt u een nieuw React Native-project:
react-native init RNAnimation
Als u React Native Web Starter gebruikt, kunt u als volgt een nieuw project maken:
git clone https://github.com/grabcode/react-native-web-starter.git RNAnimation cd RNAnimation rm -rf .git npm install
Open de index.android.js (of index.web.js) Bestand, verwijder de standaardcode en voeg het volgende toe:
import Reageren, Component uit 'reageren'; importeer App van './app/components/App'; importeer AppRegistry, View van 'react native'; klasse RNAnimation breidt Component render () return (uit (); AppRegistry.registerComponent ('RNAnimation', () => RNAnimation);
Als je React Native for Web gebruikt, kun je de bovenstaande stap overslaan omdat de standaardcode al is ingesteld om de. Te gebruiken App
bestanddeel.
Creëer een app / components
map en binnenkant maken een App.js
het dossier. Dit is het primaire bestand waarmee we gaan werken. Nadat u het bestand hebt gemaakt, kunt u doorgaan en de pakketten importeren die u nodig hebt voor het hele project.
import Reageren, Component uit 'reageren'; import Platform, StyleSheet, Text, ScrollView, View, Image, TouchableHighlight, Switch, Dimensions, Animated, Easing, LayoutAnimation, UIManager van 'react native';
Als je al eerder een soort van React Native ontwikkeling hebt gedaan, zou je al behoorlijk bekend moeten zijn met de volgende componenten. Als dat niet het geval is, bekijk dan de React Native API-documenten.
Platform, StyleSheet, Tekst, ScrollView, View, Afbeelding, TouchableHighlight, Switch, Dimensions,
Dit zijn de pakketten die specifiek worden gebruikt voor het implementeren van animaties:
Animated, Easing, LayoutAnimation, UIManager
Hier is een kort overzicht van elk:
), tekst (
) en afbeeldingen (
).UIManager
.De eerste stap bij het maken van een animatie is het definiëren van een geanimeerde waarde. Dit wordt meestal gedaan binnen de componentconstructor. In de onderstaande code definiëren we een nieuwe geanimeerde waarde voor de App
component constructor. Houd er rekening mee dat de naam van deze waarde van alles kan zijn zolang deze de animatie beschrijft die u wilt maken.
In React Native kun je een nieuwe geanimeerde waarde maken door de Waarde()
methode in de Animated
klasse. Geef vervolgens de oorspronkelijke geanimeerde waarde als het argument.
constructor (rekwisieten) super (rekwisieten); this.spinValue = new Animated.Value (0);
Maak vervolgens de functie waarmee de rotatie-animatie wordt uitgevoerd.
Op de eerste regel moeten we de beginwaarde van de geanimeerde waarde instellen waarmee we willen werken. In dit geval stellen we het in op 0.
Vervolgens maken we een nieuwe timing-animatie door de Animated.timing ()
functie. Hiermee wordt de huidige geanimeerde waarde als het eerste argument en een object met de animatieconfiguratie als de tweede geaccepteerd. Het object moet de uiteindelijke waarde bevatten voor de geanimeerde waarde, de duur (in milliseconden) en het type versnellingsanimatie.
Tot slot belt u de begin()
methode om de animatie te starten.
spin () this.spinValue.setValue (0); Animated.timing (this.spinValue, toValue: 1, duration: 1500, easing: Easing.linear) .start ();
De laatste stap is om de animatie daadwerkelijk te implementeren. In jouw render ()
methode, definieer hoe de rotatiewaarde zal worden gewijzigd. Dit kan gedaan worden door de interpoleren()
functie. Het accepteert een object dat een bevat Invoerbereik
en outputRange
. Invoerbereik
is een array met de begin- en eindrotatiewaarde. outputRange
is een array met de werkelijke rotatiewaarden.
Dus in eerste instantie zal het te animeren object op 0 graden rotatie zijn en de uiteindelijke waarde 360 graden zijn. Deze rotatie wordt uitgevoerd in de loop van 1.500 milliseconden, zoals eerder gedefinieerd in de animatieconfiguratie.
const spin = this.spinValue.interpolate (inputRange: [0, 1], outputRange: ['0deg', '360deg']);
Wanneer u de component rendert, wordt de rotatiewaarde toegevoegd als een transformatie in de stijlen. Dus als u bekend bent met CSS-animaties, is dit de equivalente implementatie in React Native.
terugkeer ();
Nu u de basiskennis van het maken van animaties kent, laten we er nog een paar maken zodat u weet hoe u verschillende soorten kunt implementeren. In jouw constructor ()
, maak een object met de animaties die we zullen implementeren:
var animations = [animation: 'spin', ingeschakeld: false, animation: 'scale', enabled: false, animation: 'opacity', enabled: false, animation: 'colorChange', enabled: false , animation: 'parallelTranslateX', ingeschakeld: false];
Maak je geen zorgen als je niet weet wat een ieder doet - ik zal je door ze allemaal heen leiden. Het enige dat u nu nog moet weten, is dat deze configuratie aangeeft of een animatie momenteel is ingeschakeld of niet. Nadat het is geïnitialiseerd, voegt u het toe animaties
array naar de staat:
this.state = animaties: animaties;
In uw render ()
functie, voeg de componenten toe die we zullen animeren, evenals de lijst met animaties.
terugkeer (); This.renderAnimationsList ()
De renderAnimationsList ()
functie maakt de lijst met animaties met gebruik Schakelaar
en Tekst
componenten.
renderAnimationsList () return this.state.animations.map ((item) => retourneer (); ); this.toggleAnimation (item.animation, value) style = styles.switch waarde = item.enabled /> Item.animation
Schakelaar
stelt de gebruiker in staat om animaties aan en uit te zetten. Telkens wanneer de gebruiker de schakelaar omdraait, wordt de toggleAnimation ()
functie wordt uitgevoerd. Het enige dat het doet is de betreffende animatie vinden en de waarde van de animatie bijwerken ingeschakeld
eigenschap naar de geselecteerde waarde. Vervolgens wordt de status bijgewerkt met de bijgewerkte waarden en worden alle animaties doorlopen, waarbij alleen de ingeschakelde worden uitgevoerd.
toggleAnimation (animatie, waarde) var animations = this.state.animations; var index = animations.findIndex ((obj) => return obj.animation == animation;); animaties [index] .enabled = waarde; this.setState (animations: animations); animations.forEach ((item) => if (item.enabled) this [item.animation] (););
Voeg ook de stijlen toe die in de hele app worden gebruikt.
const styles = StyleSheet.create (container: flex: 1, alignItems: 'center', flexDirection: 'column', button: height: 40, backgroundColor: '#eee', justifyContent: 'center', alignItems: 'midden', marginTop: 10, item: flex: 2, flexDirection: 'row', height: 50,, switch: marginBottom: 10, animation_type: marginLeft: 10, spinner: marginTop: 20 , alignSelf: 'center', width: 50, height: 50, box: width: 50, height: 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' , vierkant: width: 35, height: 35, backgroundColor: 'lightblue', margin: 10, number: fontSize: 20, fontWeight: 'bold');
Schaalanimatie is waar u een object groter of kleiner dan zijn oorspronkelijke grootte maakt. Begin met het maken van een nieuwe geanimeerde waarde binnen de constructor:
this.scaleValue = nieuwe Animated.Value (0);
Maak de functie voor het animeren van de schaal. Dit lijkt op het draai ()
functie; het enige verschil is de versnellingsfunctie die we gebruiken. Hier gebruiken we easeOutBack
om de schaal meer vloeibaar te maken. Dit is handig, vooral als deze animatie herhaaldelijk wordt uitgevoerd. Als je wilt weten welke andere easing-functies je kunt gebruiken, ga dan naar easings.net. Alle hier vermelde versoepelingen kunnen worden gebruikt in 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 ( ););
Het andere ding dat nieuw is in de bovenstaande functie is dat we een functie doorgeven als argument voor de begin()
functie. Deze functie wordt uitgevoerd wanneer de animatie is voltooid. Hier controleren we of de animatie is ingeschakeld en als dit het geval is, bellen we opnieuw dezelfde functie. Hierdoor kunnen we de animatie herhaaldelijk uitvoeren zolang deze is ingeschakeld.
() => if (this.state.animations [0] .enabled) this.scale ();
Vervolgens in uw render ()
functie, configureer de schaalinterpolatie. Deze keer hebben we drie waarden voor het invoer- en uitvoerbereik om een pulserend effect te creëren, zoals een hartslag. Hiermee kunnen we een schaalanimatie maken die een object niet abrupt groter of kleiner maakt. Het hoogste uitvoerbereik is 7, dus het object is zeven keer groter dan het oorspronkelijke formaat.
const nearFar = this.scaleValue.interpolate (inputRange: [0, 0.5, 1], outputRange: [1, 7, 1]);
Om ruimte te besparen, voegt u gewoon de schaal
transformeren op dezelfde component die we eerder gebruikten:
Met deze twee transformaties toegevoegd, kunt u nu zowel de spin- als de schaalanimatie inschakelen om ze tegelijkertijd uit te voeren.
Inmiddels zou je de patronen moeten hebben opgemerkt waarmee we animaties kunnen maken. Veel code wordt herhaald bij het doen van animaties. Het beste is om functies te maken die herhaalde code bevatten, maar om de dingen eenvoudig en gemakkelijk te begrijpen te houden, houden we ons aan de onbewerkte code voor de rest van de animaties.
Laten we nu proberen de dekking van een component te animeren. Inmiddels zou je goed bekend moeten zijn met waar elk stuk code naartoe gaat, dus ik ga niet langer vermelden waar je elk stuk code zult plaatsen. Maar in het geval dat je in de war raakt, kun je gewoon naar de code op GitHub kijken:
this.opacityValue = new Animated.Value (0);
Maak een functie voor het wijzigen van de dekking. Bij het wijzigen van de dekking, past een lineaire easing-functie het best, omdat deze de meest rechtlijnige is.
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 ( ););
Wijzig de dekking van zichtbaar in transparant en dan opnieuw zichtbaar in drie seconden.
const opacity = this.opacityValue.interpolate (inputRange: [0, 0.5, 1], outputRange: [1, 0, 1]);
Maak een nieuwe component waarvan de dekking wordt gecontroleerd:
Laten we vervolgens proberen de achtergrondkleur van een component te animeren:
this.colorValue = nieuwe Animated.Value (0);
Deze keer animeren we in de loop van vijf seconden:
colorChange () this.colorValue.setValue (0); Animated.timing (this.colorValue, toValue: 100, duration: 5000). Start (() => if (this.state.animations [3] .enabled) this.colorChange (););
We hebben drie kleuren om mee te werken. De beginkleur is geel en na enkele seconden wordt deze volledig oranje en vervolgens rood. Merk op dat de kleuren niet abrupt veranderen; alle kleuren tussen de kleuren die u hebt opgegeven, worden ook weergegeven. React Native berekent automatisch de kleurwaarden tussen de waarden die u hebt opgegeven. U kunt de duur langer maken als u wilt zien hoe de kleur in de loop van de tijd verandert.
const colorAnimation = this.colorValue.interpolate (inputRange: [0, 50, 100], outputRange: ['yellow', 'orange', 'red']);
Net als de dekking, wordt de geïnterpoleerde waarde toegevoegd als een stijl:
Je kunt zeggen dat we al animaties parallel hebben uitgevoerd. Maar dat is slechts een bijwerking van het feit dat verschillende transformaties aan een enkele component zijn gekoppeld. Als u meerdere animaties tegelijkertijd wilt uitvoeren, moet u de parallel()
functie van de geanimeerde API. Dit accepteert een reeks animatiefuncties om uit te voeren. In het onderstaande voorbeeld hebben we twee geanimeerde waarden, één voor elke component die we willen animeren.
this.blue_box_X = nieuwe Animated.Value (0); this.green_box_X = nieuwe Animated.Value (0);
In de animatiefunctie stellen we de oorspronkelijke geanimeerde waarden in zoals gebruikelijk. Maar daaronder gebruiken we Animated.parallel ()
om alle animaties te groeperen die we willen uitvoeren. In dit geval hebben we slechts twee timinganimaties, die twee seconden worden uitgevoerd. Merk ook op dat we de. Niet aanroepen begin()
methode voor elke animatie. In plaats daarvan gebruiken we het na het declareren van de parallelle animatie. Hierdoor kunnen we de animaties tegelijkertijd starten.
parallelTranslateX () this.blue_box_X.setValue (0); this.green_box_X.setValue (0); Geanimeerd.parallel ([Animated.timing (this.blue_box_X, toValue: 1, duur: 2000, easing: Easing.linear), Animated.timing (this.green_box_X, toValue: 1, duration: 2000, easing: Easing .linear)]). start (() => if (this.state.animations [4] .enabled) this.parallelTranslateX (););
Om de interpolatie zinvol te maken, controleert u eerst de stijl die we eerder hebben toegevoegd voor de twee vakken:
blue_box: alignSelf: 'flex-start', backgroundColor: 'blue', green_box: alignSelf: 'flex-end', backgroundColor: 'green',
Het blauwe vak wordt uitgelijnd met behulp van flex-start
, wat betekent dat het links uitgelijnd is. De groene doos is flex-end
, die is uitgelijnd aan de rechterkant. (Althans, dit is hoe ze werken als de container een heeft flexDirection
van kolom
. Anders is het een ander verhaal.)
Met deze kennis kunnen we nu de dozen verplaatsen waar en wanneer we maar willen. Maar voor deze tutorial is alles wat we willen doen de vakjes verplaatsen naar het tegenovergestelde van hun oorspronkelijke posities. Het blauwe vak beweegt naar rechts en het groene vak beweegt naar links. Dit is waar de apparaatdimensiegegevens binnenkomen. We gebruiken de breedte
van het apparaat om de uiteindelijke interpolatiewaarde te berekenen, zodat de box geen grenzen overschrijdt.
var width = Dimensions.get ('venster');
In dit geval trekken we eenvoudigweg af 50
van de breedte van het apparaat om het blauwe vak naar rechts te laten gaan. En voor de groene box converteren we de breedte van het apparaat naar het negatieve equivalent, zodat het naar links verplaatst. Je vraagt je misschien af, waarom 50? Dit komt omdat de grootte van elke doos is 50
. De doos zal nog steeds buiten de grenzen raken als we zijn eigen formaat niet van de breedte van het apparaat aftrekken.
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],);
Voeg ten slotte de componenten toe die moeten worden geanimeerd. De transformatie in kwestie is translateX
, waarmee we de positie van een object in de X-as kunnen wijzigen om het horizontaal te verplaatsen.
Afgezien van parallelle animaties, zijn er ook de opeenvolging en verspringende animaties.
De implementatie hiervan is vergelijkbaar met parallelle animaties in de zin dat ze allemaal een reeks animaties accepteren om te worden uitgevoerd. Maar de bepalende factor voor reeksanimaties is dat de animaties die u in de array hebt geleverd, achter elkaar worden uitgevoerd. Je kunt ook optionele vertragingen toevoegen aan elke animatie als je wilt.
Aan de andere kant is een spreidingsanimatie een combinatie van parallelle en reeksanimaties. Dit komt omdat u hiermee animaties zowel parallel als in volgorde kunt uitvoeren. Hier is een pen die spreidingsanimaties laat zien.
Een andere tool die React Native biedt voor het implementeren van animaties is LayoutAnimation
. Hiermee kunt u weergaven in hun nieuwe posities animeren wanneer de volgende lay-out plaatsvindt. Wijzigingen in de indeling treden meestal op wanneer u de status bijwerkt. Dit resulteert erin dat een specifieke UI-component wordt toegevoegd, bijgewerkt of van het scherm wordt verwijderd.
Wanneer deze gebeurtenissen gebeuren, LayoutAnimation
zorgt voor het animeren van het betreffende onderdeel. Als u in een takenlijst-app bijvoorbeeld een nieuw actiepunt toevoegt, wordt automatisch een veeranimatie toegevoegd om het nieuwe item op te laten komen.
Laten we er een toevoegen LayoutAnimation
in de gootsteen app. Zoals eerder vermeld, moet u importeren LayoutAnimation
, Platform
, en UIManager
in de app. Vervolgens in uw constructor ()
, voeg de code toe om in te schakelen LayoutAnimation
op Android:
if (Platform.OS === 'android') UIManager.setLayoutAnimationEnabledExperimental (true);
(Op iOS, LayoutAnimation
zou standaard moeten werken. Als u React Native voor internet gebruikt, wordt LayoutAnimation niet ondersteund, dus u moet de app naar Android of iOS exporteren en vanaf daar proberen.)
Vervolgens rechts onder de ScrollView
die de animatielijst bevat, voeg een knop toe voor het genereren van vierkanten die op het scherm worden getoond:
Vier vierkantjes toevoegen
Wat dit in feite zal doen, is om drie kleine vierkanten te maken telkens wanneer de gebruiker op de Vier vierkantjes toevoegen knop.
Hier is de functie voor het toevoegen van vierkanten:
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var squares = this.state.squares; this.setState (vierkanten: vierkanten + 3);
Het idee is om de LayoutAnimation.configureNext ()
voordat u de status bijwerkt. Hiermee accepteert u de animatie die u wilt gebruiken. Uit de doos, LayoutAnimation
wordt geleverd met drie presets: lineair
, de lente
, en easeInEaseOut
. Deze zouden in de meeste gevallen moeten werken, maar als je de animaties moet aanpassen, kun je de documentatie over LayoutAnimation lezen om te leren hoe je je eigen kunt maken.
Binnen in de render ()
functie, maak een voor
lus die de vierkanten maakt. Het aantal te genereren vierkanten hangt af van de huidige waarde van pleinen
in de staat.
var vierkanten = []; for (var i = 0; i < this.state.squares; i++) squares.push(this.renderSquare(i));
De renderSquare ()
functie is degene die de vierkanten daadwerkelijk rendert:
renderSquare (sleutel) retour ();
React Native's Animated API is zeer robuust en aanpasbaar, maar zoals je tot nu toe hebt gezien, heeft dit als nadeel dat je veel code moet schrijven om heel eenvoudige animaties te implementeren. In dit laatste deel introduceer ik u twee bibliotheken van derden waarmee u algemene animaties met minder code kunt implementeren.
Als u een app maakt die nummers moet animeren (bijvoorbeeld een stopwatch of een tell-app), kunt u de ingebouwde app gebruiken setInterval ()
functie om de status bij een ingesteld interval bij te werken en vervolgens de animaties zelf te implementeren.
Of als u wilt, kunt u de Animate Number-bibliotheek gebruiken. Hiermee kunt u eenvoudig nummeranimaties implementeren, zoals het aanpassen van de overgang telkens wanneer het nummer wordt bijgewerkt. U kunt het met de volgende opdracht installeren:
npm install react-native-animate-number --ave
Na installatie, importeer het in uw app:
importeer AnimateNumber van 'react-native-animate-number';
Gebruik het dan als een component:
Wat de bovenstaande code doet, telt tot 100 vanaf 0.
Als u algemene animaties wilt implementeren zoals die worden aangeboden door de bibliotheek animate.css, is er een equivalente bibliotheek voor React Native genaamd Animatable. U kunt het met de volgende opdracht installeren:
npm install react-native-animatable --save
Na installatie, importeer het met de volgende code:
importeer * als Animatable van 'react-native-animatable';
Hier is een voorbeeld met de code die we eerder hebben toegevoegd voor onze lay-outanimatie. Het enige dat u hoeft te doen is gebruiken
in plaats van
en voeg dan een toe ref
dus we kunnen naar dit onderdeel verwijzen met JavaScript-code.
Vierkanten
Maak vervolgens een resetSquares ()
methode. Hiermee worden alle vakjes verwijderd die zich momenteel op het scherm bevinden. Gebruik this.refs.squares
om naar de vierkantjescontainer te verwijzen en vervolgens de zoomOutUp ()
functie om het buiten beeld te animeren met een uitzoomanimatie met de richting omhoog. En vergeet niet om de status bij te werken nadat de animatie is voltooid. Dit is een gebruikelijk patroon bij het implementeren van animaties. Voer de animatie uit voordat u de status bijwerkt.
resetSquares () this.refs.squares.zoomOutUp (1500) .then (() => this.setState (squares: 0););
Hetzelfde geldt voor de addSquares ()
methode. Maar deze keer animeren we de vierkantjescontainer weer. En in plaats van eerst de animatie uit te voeren, doen we het meteen nadat de status is bijgewerkt. Dit komt omdat de vierkantjescontainer niet echt wordt weergegeven, tenzij er een kind is. Dus hier breken we de regel dat de animatie als eerste moet worden uitgevoerd.
addSquares () LayoutAnimation.configureNext (LayoutAnimation.Presets.spring); var squares = this.state.squares; if (vierkanten == 0) this.setState (vierkanten: vierkanten + 3, () => this.refs.squares.zoomInDown (1);); else this.setState (vierkanten: vierkanten + 3);
Dat is het! In dit artikel heb je de basis geleerd van het maken van animaties in React Native. Animaties kunnen worden geïmplementeerd met behulp van de geanimeerde API, LayoutAnimations
, en bibliotheken van derden.
Zoals u hebt gezien, kan het maken van animaties een aanzienlijke hoeveelheid code in beslag nemen, zelfs voor eenvoudige, zoals een schaalanimatie. Dit komt met het voordeel dat je de animaties op elke gewenste manier kunt aanpassen.
Als u echter niet met te veel code te maken wilt krijgen, kunt u altijd React Native-bibliotheken van derden gebruiken die specifiek zijn gemaakt voor het eenvoudig implementeren van animaties. Je vindt de volledige broncode die in deze tutorial wordt gebruikt op GitHub.
Als u tenslotte meer wilt weten over CSS-animaties, bekijk dan enkele van onze videocursussen.