O React Native expõe uma API chamada Animated. Consiste em muitas coisas maravilhosas, como valores de animação, animações de primavera / cronometragem e eventos. Mas não estamos aqui para discutir a API, deixarei isso para o documentos oficiais e meu Lista de reprodução do YouTube. Eles fazem um trabalho muito melhor cobrindo isso para você.

O que queremos discutir aqui é, de fato, como o React Native anima as coisas na tela e o que está por trás do capô.

Nós todos sabemos isso Como o React Native funciona sob o capô do meu outro artigo. (Leia rapidamente se não tiver). Como o React Native usa o React e o JavaScript, existem precisamente duas maneiras pelas quais as animações na tela podem ser realizadas. Primeiro de tudo, vamos esclarecer um fato. O React Native constrói visualizações nativas reais na tela, e não as renderizadas por meio de um navegador da Web incorporado, como o Ionic. Por esse motivo, se você deseja animar uma exibição de alguma forma, isso deve ser feito na exibição nativa. O JavaScript precisa se comunicar de alguma forma com o sistema operacional que a exibição precisa ser atualizada. O JavaScript é executado em um segmento diferente do segmento da interface do usuário (segmento principal), e somente esse segmento da interface do usuário pode atualizar as visualizações. Portanto, o JS precisa usar a ponte que o React Native fornece para serializar e comunicar esses dados ao SO.

Trabalhe em JS e atualize a visualização nativa

Essa abordagem significa que você tem uma visão que já está visível na tela do usuário e trabalha no que precisa ser feito para sua próxima posição no encadeamento JavaScript. As etapas são mais ou menos assim:

  1. Animação começa
  2. O JavaScript é executado requestAnimationFrame função - uma função que tentativas para executar a 60 chamadas / segundo (60 FPS)
  3. JavaScript calcula a próxima posição / opacidade / transformação / o que você estiver animando na exibição.
  4. JavaScript serializa esse valor e o envia pela ponte.
  5. No outro extremo da ponte, Java (Android) ou Objective C (iOS) desserializa esse valor e aplica as transformações fornecidas na exibição mencionada.
  6. O quadro é atualizado na tela.

Você viu o que aconteceu lá? Não havia nenhuma etapa envolvida na qual renderizamos novamente um componente React Native. Isso significa que, na verdade, a API animada "ignora" a filosofia do React de não alterar variáveis ​​de "estado". Isso é realmente útil no caso de animações, porque será muito lento e com desempenho ruim se permitirmos que o React renderize novamente um componente 60 vezes por segundo!

Parece tudo bom e bom, mas há um problema muito fundamental aqui. O JavaScript é único e a natureza assíncrona do JavaScript não funciona aqui porque as animações são tarefas vinculadas à CPU. Vamos dar uma olhada nos prós e contras dessa abordagem:

Prós

  1. Você pode ter animações muito sofisticadas escritas em JS e visíveis como animações nativas.
  2. Mais controle sobre o estado da animação

Contras

  1. Grande penalidade de desempenho se o seu segmento JavaScript estiver super ocupado.
  2. Bridge está ocupado, desempenho reduzido OS / JS quer se comunicar.

Esse golpe é um grande golpe para ser honesto. Há um vídeo mais adiante no artigo, que realmente mostraria isso em tempo real, e como JS estraga muito as animações quando o encadeamento JavaScript fica ocupado.

Por que as animações JS ficam atrasadas?

As animações feitas por JS começam a ficar lentas quando a animação está em andamento e o usuário (ou aplicativo) solicita alguma outra ação que deve ser tratada pelo encadeamento JS. Por exemplo, considere uma animação em andamento. Isso significa que JS está ocupado executando o requestAnimationFrame função. Supondo que as atualizações não sejam muito pesadas, vamos supor que agora o usuário comece a tocar em um botão na tela que incrementa um contador. Agora, o que está acontecendo é com o requestAnimationFrame sendo chamada com frequência, sua árvore virtual do React também é re-renderizada repetidamente para contabilizar o aumento do contador. Ambos são tarefas vinculadas à CPU em execução em um único encadeamento; portanto, haveria um impacto no desempenho. requestAnimationFrame começaria a soltar quadros por causa do trabalho adicional sendo realizado pelo encadeamento JS e você obterá uma animação muito instável.

Animações de driver nativo

Não se preocupe, porque o React Native realmente permite que você execute animações no driver nativo também! O que quero dizer com isso? Você pode perguntar. Bem, simplificando, isso significa que o React Native descarrega o trabalho de animação do encadeamento JS para o encadeamento da UI (o SO) e permite que ele lide com a animação do objeto. Isso tem alguns benefícios:

  1. O encadeamento JS (e a ponte React Native) agora está livre para lidar com outras tarefas intensivas - como toques repetitivos do usuário.
  2. As animações são muito mais suaves por causa de nenhuma sobrecarga de serialização / desserialização e comunicação de ponte.

Como o React Native consegue isso? Para isso, o que o pessoal do React Native fez é permitir que você, como desenvolvedor, forneça uma propriedade chamada useNativeDriver como um valor booleano quando você está construindo um objeto de animação. Quando definido como verdadeiro, o React Native, antes de iniciar a animação, serializava todo o estado da animação e o que precisa ser feito no futuro e o transferia uma vez pela ponte para o sistema operacional. A partir de então, o código Java (Android) ou Objective C (iOS) executaria as animações em vez do JavaScript calcular o próximo quadro de animação e enviar esses dados repetidamente pela ponte.

Isso acelera bastante as animações e as animações seriam muito mais suaves, especialmente em dispositivos de gama baixa. Vamos ver uma demonstração em vídeo de animações nativas baseadas em animações v / S JS no React Native:

Nesse caso, as etapas são mais ou menos assim:

  1. Animação começa
  2. JS serializa as informações da animação e as envia pela ponte.
  3. No outro extremo, o sistema operacional recebe essas informações e executa a animação nativamente.

É isso aí! Muito mais leve para o encadeamento JS agora. Não mais requestAnimationFrame corrida.

No entanto, ele tem sua própria parcela de prós e contras.

Prós:

  1. Animações mais rápidas
  2. Encadeamento JS sem bloqueio
  3. Ponte menos inchada

Contras:

  1. Menos controle sobre as animações (o JS não consegue ver o que está acontecendo na tela depois que a animação “automática” é iniciada)
  2. Menos propriedades para manipular – o driver nativo não suporta todas as propriedades a serem animadas, como width ou height não é nativamente animado, mas opacity e transform é.

Em muitos casos, você descobrirá que pode solucionar um conjunto diferente de animações usando o useNativeDriver: true para criar um efeito semelhante que não pode ser alcançado sem definir useNativeDriver: false. A equipe do React Native está trabalhando para adicionar suporte a mais propriedades enquanto falamos, mas por enquanto, acredito que seja ótimo no momento.

Conclusão

Este artigo mostrou como as animações do React Native realmente funcionam sob o capô e por que é bonito. O que você acha deste artigo? Diga-me conectando comigo no meu Instagram e Twitter contas! Novo no React Native? Comece a aprender codedamn – uma plataforma para os desenvolvedores aprenderem e se conectarem!

Paz!