Como funciona a API Animated do React Native?

Letícia Chijo
React Brasil

--

Toda vez que eu via uma animação em um aplicativo, seja uma transição gradual entre telas ou um botão que gira ao mostrar mais opções, ficava muito admirada. Me parecia algo muitíssimo complexo de ser feito e que adiciona bastante personalidade e interesse a uma tela.

Até que recentemente surgiu a necessidade de fazer algumas animações em componentes react native nos quais eu estava trabalhando. Num primeiro momento achei que seria uma tarefa muito custosa, mas foi quando descobri que o react native possui uma API que se propõe a fazer animações de maneira razoavelmente simples: a Animated. E hoje vamos falar um pouquinho sobre como você pode começar a fazer as suas próprias animações usando essa ferramenta!

Mas como funciona essa API?

A ideia principal é utilizar uma das funções de animação fornecidas pela API passando para ela um input que irá refletir em algum elemento visual da sua tela. Por exemplo: podemos dizer para alguma dessas funções que queremos pegar um texto com tamanho de fonte 10 e transformá-lo gradativamente em um texto com tamanho 20.

E quais são essas funções? O que elas fazem?

A função de animação vai determinar qual é o tipo de movimentação que veremos acontecer na tela, sendo que a API fornece 3 opções:

  • Animated.timing(): realiza a movimentação em um determinado intervalo de tempo.
  • Animated.spring(): cria um movimento oscilatório inspirado em uma mola.
  • Animated.decay(): o movimento começa com uma certa velocidade que diminui até parar.

Então, voltando ao nosso exemplo anterior onde queremos alterar o tamanho da fonte: se usássemos a primeira função da nossa lista, a Animated.timing(), poderíamos dizer: varie gradativamente o valor do tamanho da fonte, começando de 10 e indo até 20, num intervalo de 2 segundos.

Na prática

Para criar uma animação, passaremos então por 3 etapas:

  1. Instanciar o valor da animação;
  2. Configurar a função escolhida;
  3. Atrelar a animação a um elemento e mudar suas propriedades com base no valor da animação.

A seguir vamos fazer um exemplo básico utilizando as 3 diferentes funções de animação (timing, springe decay) e assim poderemos observar de maneira bem clara a diferença entre elas.

Para isso, vamos começar com uma tela simples: três quadrados coloridos que irão se mover de uma posição inicial até uma posição final, verticalmente, quando um botão for pressionado.

Aqui em baixo você pode conferir o código inicial dessa tela:

Agora vamos fazer algumas modificações nesse código para aplicar a cada quadrado uma das opções de função de animação.

Timing

Passo 1) começamos instanciando o valor da animação. Nesse tutorial, vamos fazer isso usando o Hook useState.

const [redSquareAnim] = useState(new Animated.Value(0))

Passo 2) agora podemos configurar a função timing. Precisamos dizer qual é o valor da animação a ser utilizado (nesse caso, o redSquareAnim que criamos no passo anterior) e as configurações da animação em si.

Queremos que o redSquareAnim (que começa em 0) vá para o valor 200 gradualmente durante 1000 milissegundos (ou seja, 1 segundo).

Animated.timing(redSquareAnim, {toValue: 200, duration: 1000})

Mas queremos que essa animação comece quando pressionarmos o botão “Timing”. Para isso, vamos criar uma função que será chamada pelo botão e que inicia esta animação:

const onPressTiming = () => {
Animated.timing(redSquareAnim, {toValue: 200, duration: 1000}).start()
}

Passo 3) Vamos atrelar essa animação ao nosso quadrado vermelho. Para receber uma animação, precisamos transformar a nossa <View> em uma <Animated.View> que será capaz de modificar seus parâmetros conforme nossa função definida no passo 2.

Queremos que a posição em Y do quadrado varie de 0 a 200. Para fazer isso, podemos utilizar a propriedade de estilo transform que, dentre outras coisas, permite alterar a posição de um elemento.

<Animated.View style={{
backgroundColor: 'red',
height: 50,
width: 50,
marginBottom: 20,
transform: [{translateY: redSquareAnim}]
}}/>

E pronto! Temos a nossa primeira animação.

Spring

Nosso quadrado amarelo deve, também, mudar de posição quando apertamos o botão. Mas queremos que ele faça isso com um movimento mais interessante: um vai-e-vem que imita uma mola.

Para configurar essa mola, existem algumas combinações de parâmetros que podemos alterar:

  • speed/bounciness
  • friction/tension
  • swiftness/damping/mass

São várias maneiras diferentes de controlar a mola, mas utilizando qualquer uma delas é possível chegar ao mesmo resultado. Para esse tutorial, vamos usar o conjunto speed/bounciness, onde speed controla a velocidade do movimento e bounciness controla o quanto nosso quadrado vai oscilar antes de parar.

Os passos para fazer essa animação são semelhantes aos apresentados no quadrado vermelho:

Passo 1)

const [yellowSquareAnim] = useState(new Animated.Value(0))

Passo 2)

const onPressSpring = () => {
Animated.spring(yellowSquareAnim, {toValue: 200, speed: 10, bounciness: 20}).start()
}

Passo 3)

<Animated.View style={{
backgroundColor: 'yellow',
height: 50,
width: 50,
marginBottom: 20,
transform: [{translateY: yellowSquareAnim}]
}}/>

E com isso temos a segunda animação funcionando!

Decay

Por fim, temos a função do tipo decay. Ela tem uma particularidade: não é necessário colocar o valor final que ela deve atingir. O seu movimento é controlado por uma velocidade inicial e sua desaceleração. Desta forma, podemos seguir os mesmos passos com uma pequena mudança no passo 2:

Passo 1)

const [blueSquareAnim] = useState(new Animated.Value(0))

Passo 2) Aqui não utilizaremos a configuração toValue. Basta colocar uma velocidade inicial e uma desaceleração.

const onPressDecay = () => {
Animated.decay(blueSquareAnim, {velocity: 0.41, deceleration: 0.998}).start()
}

Passo 3)

<Animated.View style={{
backgroundColor: 'blue',
height: 50,
width: 50,
marginBottom: 20,
transform: [{translateY: blueSquareAnim}]
}}/>

E por fim temos nossa última animação pronta!

Agora você pode experimentar mudar as configurações que colocamos para cada tipo de animação no passo 2 para entender melhor como elas reagem.

Você pode ver o aplicativo completo neste link. E se quiser ver como ficou o código final da nossa tela, clique aqui para ir para o meu git hub :)

--

--