
A animação em aplicativos React é um tópico popular e discutido. O fato é que existem muitas maneiras de criá-lo. Alguns desenvolvedores usam CSS adicionando tags às classes HTML. Um excelente método que vale a pena usar. Mas se você quer trabalhar com tipos complexos de animações, vale a pena dedicar um tempo para aprender o GreenSock, é uma plataforma popular e poderosa. Existem também muitas bibliotecas e componentes para a criação de animações. Vamos falar sobre eles.
Este artigo discute cinco maneiras de animar aplicativos React:
- CSS;
- Grupo ReactTransition;
- Animações de reação;
- Reagir-revelar;
- TweenOne e Ant Design.
A Skillbox recomenda: Curso educacional on-line .
Lembramos: para todos os leitores de "Habr" - um desconto de 10 rublos ao se inscrever em qualquer curso Skillbox usando o código promocional "Habr".
Todos os exemplos estão disponíveis em (a partir daqui as fontes são inseridas no artigo em vez de imagens, como no artigo original).
APF
Esse método foi discutido no início e é muito bom. Se, em vez de importar bibliotecas JavaScript, você usar, a montagem for pequena, o navegador não precisa de muitos recursos. E isso, claro, afeta o desempenho do aplicativo. Se sua animação precisa ser relativamente simples, considere este método.
Por exemplo, aqui está um menu animado:

É relativamente simples, com uma propriedade CSS e um gatilho como className="is-nav-open" na tag HTML.
Este método pode ser usado de diferentes maneiras. Por exemplo, crie um wrapper acima da navegação e, em seguida, cause alterações nos campos. Como a navegação tem uma largura constante de 250px, a largura de um wrapper com uma propriedade margin-left ou translateX deve ter a mesma largura. Se você precisar mostrar a navegação, adicione className = "is-nav-open" ao wrapper e mova o wrapper para margin-left/translateX: 0;.
No final das contas, a fonte da animação ficará assim:
export default class ExampleCss extends Component {
handleClick() {
const wrapper = document.getElementById('wrapper');
wrapper.classList.toggle('is-nav-open')
}
render() {
return (
<div id="wrapper" className="wrapper">
<div className="nav">
<icon
className="nav__icon"
type="menu-fold"
onClick={() => this.handleClick()}/>
<div className="nav__body">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Beatae ducimus est laudantium libero nam optio repellat
sit unde voluptatum?
</div>
</div>
</div>
);
}
}E aqui estão os estilos CSS:
.wrapper {
display: flex;
width: 100%;
height: 100%;
transition: margin .5s;
margin: 0 0 0 -250px;
}
.wrapper.is-nav-open {
margin-left: 0;
}
.nav {
position: relative;
width: 250px;
height: 20px;
padding: 20px;
border-right: 1px solid #ccc;
}
.nav__icon {
position: absolute;
top: 0;
right: -60px;
padding: 20px;
font-size: 20px;
cursor: pointer;
transition: color .3s;
}
.nav__icon:hover {
color: #5eb2ff;
}Novamente, se a animação for relativamente simples, esse método é o principal. Os usuários ficarão satisfeitos com a velocidade do navegador.
Grupo ReactTransition
O componente ReactTransitionGroup foi desenvolvido pela equipe da comunidade ReactJS. Com sua ajuda, você pode implementar facilmente animações e transições CSS básicas.
ReactTransitionGroup foi projetado para alterar classes quando o ciclo de vida do componente muda. Ele é pequeno e precisa ser instalado em um pacote de aplicativos React, o que aumentará ligeiramente o tamanho geral da construção. Além disso, você pode usar um CDN.
ReactTransitionGroup possui três elementos, Transition, CSSTransition e TransitionGroup. Para iniciar a animação, você precisa envolver o componente neles. O estilo, por sua vez, precisa ser escrito em classes CSS.
Aqui está a animação e depois a forma de implementá-la.

A primeira etapa é importar CSSTransitionGroup do react-transition-group. Depois disso, você precisa agrupar a lista e definir a propriedade transactionName. Cada vez que um elemento filho em um CSSTransitionGroup é adicionado ou removido, ele recebe estilos de animação.
<CSSTransitionGroup
transitionName="example">
{items}
</CSSTransitionGroup>Ao definir a propriedade transactionName = "example", as classes nas folhas de estilo devem começar com o nome do exemplo.
.example-eneter {
opacity: 0.01;
}
.example-enter.example-enter-active {
opacity: 1;
transition: opacity 300ms ease-in;
}
.example-leave {
opacity: 1;
}
.example-leave.example-leave-active {
opacity: 0.01;
transition: opacity 300ms ease-in;Acima está um exemplo de uso do ReactTransitionGroup.
Também precisamos de lógica e de dois métodos para implementar o exemplo de adição de uma lista de contatos.
O primeiro método é handleAdd - ele adiciona novos contatos, obtém um nome aleatório, que então coloca no array state.items.
Para remover um contato por índice no array state.items, handleRemove é usado.
import React, { Component, Fragment } from 'react';
import { CSSTransitionGroup } from 'react-transition-group'
import random from 'random-name'
import Button from './button'
import Item from './item'
import './style.css';
export default class ReactTransitionGroup extends Component {
constructor(props) {
super(props);
this.state = { items: ['Natividad Steen']};
this.handleAdd = this.handleAdd.bind(this);
}
handleAdd() {
let newItems = this.state.items;
newItems.push(random());
this.setState({ items: newItems });
}
render () {
const items = this.state.items.map((item, i) => (
<Item
item={item}
key={i}
keyDelete={i}
handleRemove={(i) => this.handleRemove(i)}
/>
));
return (
<Fragment>
<Button onClick={this.handleAdd}/>
<div className="project">
<CSSTransitionGroup
transitionName="example"
transitionEnterTimeout={500}
transitionLeaveTimeout={300}
>
{items}
</CSSTransitionGroup>
</div>
</Fragment>
);
}
};Animações de reação
é uma biblioteca construída em animate.css. Ela é fácil de trabalhar e tem muitas coleções de animações diferentes. A biblioteca é compatível com qualquer biblioteca de estilo inline que suporte o uso de objetos para definir quadros básicos de animação, incluindo Radium, Afrodite ou componentes estilizados.

Eu sei o que você está pensando:

Agora vamos verificar como isso funciona usando o exemplo de uma animação saltitante.

Em primeiro lugar, importamos a animação das animações de reação.
const Bounce = styled.div`animação: 2s ${keyframes`${bounce}`} infinito`;
Então, após criar o componente, envolvemos qualquer código HTML ou componente para animação.
<bounce><h1>Hello Animation Bounce</h1></bounce>Exemplo:
import React, { Component } from 'react';
import styled, { keyframes } from 'styled-components';
import { bounce } from 'react-animations';
import './style.css';
const Bounce = styled.div`animation: 2s ${keyframes`${bounce}`} infinite`;
export default class ReactAnimations extends Component {
render() {
return (
<Bounce><h1>Hello Animation Bounce</h1></bounce>
);
}
}Tudo funciona, a animação é muito simples. Além disso, há uma ótima solução para usar animação de rolagem e salto - .
Reagir-revelar
Existem animações básicas, incluindo desvanecimento, inversão, dimensionamento, rotação e muito mais. Ele permite que você trabalhe com todas as animações usando adereços. Assim, você pode definir configurações adicionais, incluindo posição, atraso, distância, cascata e outras. Outros efeitos CSS podem ser usados, incluindo renderização no servidor e componentes de alta ordem. No geral, se você precisar de animação de rolagem, vale a pena usar esta estrutura.
import Fade from 'react-reveal/Fade';
<Fade top>
<h1>Title</h1>
</Fade> 
São cinco blocos no total, cada um deles com página em tela cheia e cabeçalho.
import React, { Component, Fragment } from 'react';
import Fade from 'react-reveal/Fade';
const animateList = [1, 2, 3, 4, 5];
export default class ReactReveal extends Component {
render() {
return (
<Fragment>
{animateList.map((item, key) => (
<div style={styles.block} key={key}>
<Fade top>
<h1 style={styles.title}>{`block ${item}`}</h1>
</Fade>
</div>
))}
</Fragment>
);
}
}
const styles = {
block: {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
height: '100%',
background: '#000',
borderBottom: '1px solid rgba(255,255,255,.2)',
},
title: {
textAlign: 'center',
fontSize: 100,
color: '#fff',
fontFamily: 'Lato, sans-serif',
fontWeight: 100,
},
};Agora apresentamos a constante animateList. A matriz contém cinco elementos. Após usar o método map array, é possível renderizar qualquer elemento nos componentes Fade inserindo os elementos no cabeçalho. Os estilos definidos na constante de estilos recebem estilos CSS curtos para o bloco e o cabeçalho. Acima estão cinco blocos com animação Fade.
TweenOne e animação no Ant Design
— Biblioteca React UI, que contém um grande número de componentes úteis e fáceis de usar. É adequado se você precisar criar interfaces de usuário elegantes. Foi desenvolvido pela Alibaba, que utiliza a biblioteca em muitos de seus projetos.

O exemplo tem muitos componentes animados. A maioria deles possui animações semelhantes, portanto a implementação do exemplo será mais simples que a acima. Isto incluirá apenas uma bola, uma bola verde e um elemento adicional, por exemplo, um quadrado vermelho.

A animação usa o componente TweenOne, que precisa de um PathPlugin para definir corretamente o caminho do movimento. Tudo isso funcionará apenas se você colocar
PathPlugin em TweenOne.plugins.
TweenOne.plugins.push(PathPlugin);Os principais parâmetros de animação são os seguintes:
- duração — tempo de animação em ms;
- facilidade — suavidade da animação;
- ioiô - mudando o movimento para frente e para trás a cada repetição;
- repetir - repete a animação. Precisa usar -1 para animação infinita;
- p — coordenadas do caminho para animação;
- easyPath — coordenadas do caminho suave da animação.
Os dois últimos parâmetros são bem específicos, mas você não precisa se preocupar com eles, tudo funciona como deveria.
const duration = 7000;
const ease = 'easeInOutSine';
const p =
'M123.5,89.5 C148,82.5 239.5,48.5 230,17.5 C220.5,-13.5 127,6 99.5,13.5 C72,21 -9.5,56.5 1.5,84.5 C12.5,112.5 99,96.5 123.5,89.5 Z';
const easePath =
'M0,100 C7.33333333,89 14.3333333,81.6666667 21,78 C25.3601456,75.6019199 29.8706084,72.9026327 33,70 C37.0478723,66.2454406 39.3980801,62.0758689 42.5,57 C48,46.5 61.5,32.5 70,28 C77.5,23.5 81.5,20 86.5,16 C89.8333333,13.3333333 94.3333333,8 100,0';
const loop = {
yoyo: true,
repeat: -1,
duration,
ease,
};Agora você pode começar a criar o objeto de animação.
- redSquare contém os parâmetros do loop mais a coordenada Y, duração e atraso.
- greenBall contém um caminho com parâmetros de objeto x, y é o valor de p. Além disso, duração, repetição e suavidade são funções de TweenOne.easing.path, que possui dois parâmetros.
- caminho - facilidadePath.
- lengthPixel é uma curva dividida em um total de 400 seções.
- track é uma forma oval com eixos, possui estilos de ciclo e um parâmetro de rotação.
const animate = {
redSquare: {
...loop,
y: 15,
duration: 3000,
delay: 200,
},
greenBall: {
path: { x: p, y: p },
duration: 5000,
repeat: -1,
ease: TweenOne.easing.path(easePath, { lengthPixel: 400 }),
},
track: {
...loop,
rotate: 15,
},
};Você também precisa prestar atenção ao componente TweenOne. Todos os componentes serão importados do rc-tween-one. TweenOne é um componente básico com adereços básicos e adereços de animação, que representam animação. Cada TweenOne possui seus próprios parâmetros de animação, como redSquare, track, greenBall.
import React from 'react';
import TweenOne from 'rc-tween-one';
export default function BannerImage() {
return (
<div className="wrapper-ant-design">
<svg width="482px" height="500px" viewBox="0 0 482 500">
<defs>
<path
d="M151,55 C129.666667,62.6666667 116,74.3333333 110,90 C104,105.666667 103,118.5 107,128.5 L225.5,96 C219.833333,79 209.666667,67 195,60 C180.333333,53 165.666667,51.3333333 151,55 L137,0 L306.5,6.5 L306.5,156 L227,187.5 L61.5,191 C4.5,175 -12.6666667,147.833333 10,109.5 C32.6666667,71.1666667 75,34.6666667 137,0 L151,55 Z"
id="mask"
/>
</defs>
<g stroke="none" strokeWidth="1" fill="none" fillRule="evenodd" transform="translate(0, 30)">
<g id="Group-13" transform="translate(0.000000, 41.000000)">
<TweenOne component="g" animation={animate.redSquare}>
<rect
stroke="#F5222D"
strokeWidth="1.6"
transform="translate(184.000000, 18.000000) rotate(8.000000) translate(-184.000000, -18.000000) "
x="176.8"
y="150.8"
width="14.4"
height="14.4"
rx="3.6"
/>
</TweenOne>
</g>
<g id="Group-14" transform="translate(150.000000, 230.000000)">
<g id="Group-22" transform="translate(62.000000, 7.000000)">
<image
id="cc4"
alt="globe"
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/FpKOqFadwoFFIZFExjaf.png"
width="151px"
height="234px"
/>
</g>
<mask id="mask-2">
<use xlinkHref="#mask" fill="white" transform="translate(-42, -33)" />
</mask>
<g mask="url(#mask-2)">
<TweenOne component="g" animation={animate.track} style={{ transformOrigin: '122.7px 58px' }}>
<g transform="translate(-16, -52)">
<g transform="translate(16, 52)">
<path
d="M83.1700911,35.9320015 C63.5256194,37.9279025 44.419492,43.1766434 25.8517088,51.6782243 C14.3939956,57.7126276 7.77167019,64.8449292 7.77167019,72.4866248 C7.77167019,94.1920145 61.1993389,111.787709 127.105708,111.787709 C193.012078,111.787709 246.439746,94.1920145 246.439746,72.4866248 C246.439746,55.2822262 212.872939,40.6598106 166.13127,35.3351955"
id="line-s"
stroke="#0D1A26"
strokeWidth="1.35"
strokeLinecap="round"
transform="translate(127.105708, 73.561453) rotate(-16.000000) translate(-127.105708, -73.561453) "
/>
</g>
<TweenOne component="g" animation={animate.greenBall}>
<image
alt="globe"
id="id2"
xlinkHref="https://gw.alipayobjects.com/zos/rmsportal/IauKICnGjGnotJBEyCRK.png"
x="16"
y="62"
width="26px"
height="26px"
/>
</TweenOne>
</g>
</TweenOne>
</g>
</g>
</g>
</svg>
</div>
);
} 
Sim, parece assustador, mas a animação usando esse método é simples.
<TweenOne component="g" animation={animate.redSquare} />
<TweenOne component="g" animation={animate.track} />
<TweenOne component="g" animation={animate.greenBall} />Tudo que você precisa fazer é descrever as regras de animação e transferi-las para o componente TweenOne.
Alcançar objetivos diferentes requer abordagens diferentes. Este artigo discutiu diversas soluções que podem ser usadas em um grande número de projetos. Cabe a você escolher o caminho certo.
A Skillbox recomenda:
- Curso prático de dois anos .
- Curso online .
- curso de ano prático .
Fonte: habr.com
