Gradienti d'animazione in React Native

Sto lavorando a un progetto personale chiamato KaoCards, un'app flashcard per ricordare i nomi e i volti delle persone. Quando ho progettato il prodotto, ho pensato che sarebbe stato bello avere un gradiente animato come sfondo, ma quando ho provato a implementarlo, si è rivelato più lavoro di quanto pensassi.

Quindi, ecco la storia di come sono riuscito a farlo funzionare. Se vuoi il TL; DR, ho creato un repository che puoi seguire.

Un ingenuo tentativo.

Se vuoi capirlo, è importante sapere perché il mio primo tentativo non ha funzionato.

Per visualizzare un gradiente in React Native, le persone usano un progetto chiamato gradiente lineare nativo di reazione. Volevo vedere se qualcuno avesse provato ad animare i colori e ho trovato l'esempio di Transizione gradiente animata su quel repository. Guardando attraverso il codice, ho avuto questa reazione:

Non capivo perché fossero necessarie due classi, perché c'era così tanto codice. Non pensavo che avresti bisogno di così tanto. Decisi che non mi sarei preoccupato di capire tutto ciò. Ho pensato che il modo per farlo fosse abbastanza semplice:

  1. Creare un componente AnimatedLinearGradient utilizzando Animate.createAnimatedComponent
  2. Interpolare alcuni colori e passarli a AnimatedLinearGradient

Semplice vero? Ecco la fonte (andrà in crash). Ho realizzato un'app sperimentale, l'ho eseguita e poi ho fatto womp womp. Viene visualizzato l'errore:

Il valore JSON `` di tipo NSNull non può essere convertito in UIColor. Hai dimenticato di chiamare processColor () sul lato JS?

Qualcosa da qualche parte lungo la linea non stava ottenendo i valori dei colori. Quindi ho chiesto aiuto a Twitter:

Jason Brown ha risposto con l'intuizione chiave:

Aaahhh ok! L'animazione non funziona con le matrici. Sebbene pensassi di fare tutto correttamente, la libreria animata non elabora i valori dei puntelli dell'array, quindi il componente nativo sottostante sta ottenendo spazzatura invece di ottenere colori animati.

È diventato chiaro perché l'esempio originale era così grande.

Costruendolo correttamente.

Ok, comprendendo questa limitazione su Animated, modifichiamo il nostro piano di gioco e lo rendiamo un po 'più robusto.

  1. Vogliamo che il nostro componente principale, AnimatedGradient, funzioni esattamente come LinearGradient. Dovrebbe richiedere una gamma di colori.
  2. Vogliamo che si verifichi una transizione quando cambiamo l'elica dei colori. Per fare ciò, AnimatedGradient deve tenere traccia dei colori precedenti.
  3. Dal momento che non possiamo animare i valori negli array, possiamo costruire un componente GradientHelper che prende i colori individualmente e chiamare Animated.createAnimatedComponent su quello. GradientHelper inserirà i valori in un array e li passerà al componente LinearGradient dal pacchetto di gradiente reattivo-nativo-lineare.

Per rendere le cose semplici per questo esempio, supponiamo che l'array colors abbia solo 2 valori.

Componente AnimatedGradient

Codice sorgente

Innanzitutto, creeremo un AnimatedGradientHelper dal nostro GradientHelper, che realizzeremo tra poco.

Nel costruttore di AnimatedGradient, inizializzeremo un campo di stato prevColors per tenere traccia dei colori precedenti. Inizializziamo anche un Animated.Value chiamato tweener.

In getDerivedStateFromProps prendiamo il valore state.colors e restiamo in state.prevColors. Impostiamo i nuovi state.colors e ripristiniamo il tweener.

In componentWillUpdate (ovvero quando cambiano gli oggetti di scena), faremo spostare il tweener da 0 a 1.

Nel metodo di rendering, utilizziamo il tweener, i prevColors e i colori per creare due interpolazioni di colori e passarle individualmente al nostro AnimatedGradientHelper.

Assistente gradiente

Codice sorgente

In GradientHelper, tutto ciò che stiamo facendo è prendere gli oggetti di scena color1 e color2, metterli in un array e passarli a LinearGradient. Lo stiamo facendo perché dobbiamo aggirare i limiti di Animated.

E questo è il senso. Ecco la demo:

Ora sappiamo perché l'esempio originale è così grande. Doveva fare tutte queste cose e gestire i gradienti con più di 2 colori.

Ma aspetta, cos'altro possiamo animare?

Possiamo effettivamente fare il passo in più e animare altre proprietà. Il componente LinearGradient consente di specificare le coordinate per l'inizio e la fine del gradiente. Perché non interpolare anche quelli? Ecco un metodo di rendering aggiornato. Probabilmente puoi indovinare cosa è successo nel resto del componente. fonte

Dobbiamo solo modificare un po 'il nostro GradientHelper facendo qualcosa con gli oggetti di scena. fonte

E ora abbiamo una demo più interessante.

Sono stato in grado di combinare questo gradiente animato con alcune altre animazioni per creare un fantastico effetto di sfondo per il mio progetto KaoCards:

Quindi, ora sai come animare i gradienti in React Native e un po 'di più su come funziona l'Animated. Quali altre proprietà pensi di poter animare?

Grazie a Jason Brown per aver fornito le informazioni chiave. Tutto quello che ho imparato sull'animazione di cose in React Native l'ho imparato da lui. Assicurati di seguirlo su Twitter e dai un'occhiata al suo corso React Native Animations.