Animering af gradueringer i reageret indfødt

Jeg arbejder på et personligt projekt kaldet KaoCards, en flashcard-app til at huske folks navne og ansigter. Da jeg designede produktet, syntes jeg, det ville være cool at have en animeret gradient som baggrund, men da jeg prøvede at implementere, viste det sig at være mere arbejde, end jeg troede.

Så her er historien om, hvordan jeg formåede at få det til at fungere. Hvis du vil have TL; DR, lavede jeg et lager, du kan følge med på.

Et naivt forsøg.

Hvis du vil forstå dette, er det vigtigt at vide, hvorfor mit første forsøg ikke fungerede.

For at få vist en gradient i React Native bruger folk et projekt kaldet react-native-lineær gradient. Jeg ville se, om nogen havde prøvet at animere farverne, og jeg fandt eksemplet Animeret gradientovergang på den repo. Når jeg kiggede gennem koden, fik jeg denne reaktion:

Jeg forstod ikke, hvorfor det havde brug for to klasser, hvorfor der var så meget kode. Jeg troede ikke, du ville have brug for så meget. Jeg besluttede, at jeg ikke ville gider at forstå alt dette. Jeg regnede med, at måden at få dette til skulle være ganske enkel:

  1. Opret en AnimatedLinearGradient-komponent ved hjælp af Animate.createAnimatedComponent
  2. Interpolér nogle farver, og send dem til AnimatedLinearGradient

Enkelt, ikke? Her er kilden (den går ned). Jeg lavede en eksperimentel app, kørte den, og derefter, womp womp. Vi får fejlen:

JSON-værdien `` af typen NSNull kan ikke konverteres til en UIColor. Har du glemt at kalde processColor () på JS-siden?

Noget et sted nede på linjen fik ikke farveværdier. Så jeg henvendte mig til Twitter for at få hjælp:

Jason Brown svarede med den vigtigste indsigt:

Aaahhh ok! Animeret fungerer ikke med matriser. Selvom jeg troede, at jeg gjorde alt korrekt, behandler det animerede bibliotek ikke værdierne for array-rekvisitter, så den underliggende native komponent får affald i stedet for at få animerede farver.

Det blev klart, hvorfor det originale eksempel var så stort.

Byg det korrekt.

Ok, forstå denne begrænsning om Animeret, lad os ændre vores spilplan og gøre den lidt mere robust.

  1. Vi ønsker, at vores hovedkomponent, AnimatedGradient, skal fungere som LinearGradient. Det skal tage en række farver.
  2. Vi ønsker, at der skal ske en overgang, når vi ændrer farverne. For at gøre dette skal AnimatedGradient holde styr på de forrige farver.
  3. Da vi ikke kan animere værdier i matriser, kan vi opbygge en GradientHelper-komponent, der tager farver hver for sig, og kalde Animated.createAnimatedComponent på det. GradientHelper lægger værdierne i en matrix og videregiver dem til LinearGradient-komponenten fra pakken med reaktivt native-lineær gradient.

For at holde tingene enkle til dette eksempel antager vi, at farvergruppen kun har 2 værdier.

AnimatedGradient-komponent

Kildekode

Først opretter vi en AnimatedGradientHelper ud af vores GradientHelper, som vi laver i en smule.

I konstruktøren af ​​AnimatedGradient initialiserer vi et felt i prevColors-tilstand for at holde styr på de forrige farver. Vi initialiserer også en Animated.Value kaldet tweener.

I getDerivedStateFromProps tager vi værdien state.colors og holder os i state.prevColors. Vi indstiller den nye tilstand.farver, og vi nulstiller tweeneren.

I componentWillUpdate (også kaldet, når rekvisitter ændres), får vi tweener til at gå fra 0 til 1.

I render-metoden bruger vi tweener, prevColors og farver til at oprette to farveinterpolationer og videregive dem individuelt til vores AnimatedGradientHelper.

Gradient Helper

Kildekode

I GradientHelper er alt, hvad vi laver, at tage farve1 og farve2-rekvisitterne, sætte dem i en matrix og videregive det til LinearGradient. Vi gør dette, fordi vi er nødt til at omgå Animated's begrænsninger.

Og det er kernen i det. Her er demoen:

Nu ved vi, hvorfor det originale eksempel er så stort. Det måtte gøre alt dette, og håndtere gradueringer med mere end 2 farver.

Men vent, hvad kan vi ellers animere?

Vi kan faktisk gå det ekstra skridt og animere andre egenskaber. LinearGradient-komponenten giver dig mulighed for at specificere koordinater til begyndelsen og slutningen af ​​gradienten. Hvorfor ikke interpolere dem også? Her er en opdateret gengivelsesmetode. Du kan sandsynligvis gætte, hvad der skete i resten af ​​komponenten. Kilde

Vi bliver bare nødt til at finpudse vores GradientHelper lidt ved at gøre noget med rekvisitterne. Kilde

Og nu har vi en køligere demo.

Jeg var i stand til at kombinere denne animerede gradient med nogle andre animationer for at skabe en cool baggrundseffekt til mit KaoCards-projekt:

Så ved du nu, hvordan du animerer gradueringer i React Native, og lidt mere om, hvordan Animeret fungerer. Hvilke andre egenskaber tror du, du kan animere?

Tak til Jason Brown for at give den vigtigste indsigt. Alt, hvad jeg har lært om animationsmateriale i React Native, har jeg lært af ham. Sørg for, at du følger ham på Twitter, og tjek hans React Native Animations-kursus.