Dark mode
Light mode
09 Set 19
6 min

Loaders animados com GSAP - Parte 2

A segunda parte da mini-série sobre animações usando a GreenSock Animation API

Introdução

Na primeira parte desta série de tutoriais, mostrei como criar um simples loader com GSAP, transformando um círculo num quadrado e vice-versa.

Para essa segunda parte, vamos construir algo mais divertido e um pouco mais complexo, um loader de uma bola quicando.

Estruturando o HTML

A animação que iremos criar é composta de apenas dois elementos: um elemento para a bola e outro para a sombra.

1<div class="ball"></div> 2<div class="shadow"></div>

Adicionando o CSS

Antes de tudo, costumo fazer o reset das propriedades e centralizar os elementos na tela com flexbox:

1* { 2 padding: 0; 3 margin: 0; 4 box-sizing: border-box; 5} 6 7body { 8 display: flex; 9 align-items: center; 10 justify-content: center; 11 flex-direction: column; 12 height: 100vh; 13 background-color: #ffc30f; 14}

E então estilizamos a bola e a sombra:

1.ball { 2 width: 60px; 3 height: 60px; 4 border-radius: 50%; 5 background-color: #c70039; 6 background: linear-gradient( 7 to bottom, 8 rgba(199, 0, 56, 1) 0%, 9 rgba(144, 12, 63, 1) 100% 10 ); 11 transform: translateY(-100px); 12} 13 14.shadow { 15 width: 60px; 16 height: 30px; 17 background: radial-gradient( 18 ellipse at center, 19 rgba(88, 24, 69, 1) 0%, 20 rgba(237, 237, 237, 0) 50% 21 ); 22 position: relative; 23 z-index: -1; 24 transform: translateY(75px); 25 opacity: 0.1; 26}

Perceba que:

  1. Colocamos position: relative e z-index: -1, assim garantimos que a sombra sempre estará atrás da bola, dando o efeito que desejamos.
  2. Movemos a bola um pouco para cima e a sombra um pouco para baixo, esse será o estado inicial da animação.

Estados da animação

Vamos entender o que desejamos fazer. Para isso, separei a animação em 3 estados:

Steps to Bouncy Ball

  1. No estado inicial, a bola começa um pouco pra cima do centro da tela e com uma leve sombra um pouco abaixo, como se houvesse um piso imaginário.
  2. No segundo estado, ela atinge a posição mínima, ou seja, o nosso "chão".
  3. No estado final, "amassamos" levemente a bola para simular o impacto na superfície. Também aumentamos o tamanho e a força da sombra, para simular que o objeto está mais próximo do solo.

Entendendo a linha do tempo

Great Scott!
Great Scott!

Como mencionei no artigo anterior, a GSAP é composta de 4 bibliotecas, onde podemos fazer animações isoladas ou encadeadas.

Para as animações isoladas criamos tweens usando as bibliotecas TweenLite ou TweenMax.

Para as encadeadas, utilizamos a TimelineLite ou a TimelineMax, que nos ajudam a criar uma sequencia de tweens que seguem uma ordem cronológica.

A principal vantagem de uma Timeline é que a animação pode ser controlada usando métodos como play(), stop(), restart() e reverse(), nos dando total controle sobre quando as coisas devem acontecer.

Na nossa animação, iremos usar a TimelineMax. Isso porque ela tem todas as funcionalidades da TimelineLite, e mais algumas como as propriedades yoyo e repeat - que usaremos mais adiante.

Animação da bola

Vamos começar selecionando os elementos:

1var ball = document.querySelector(".ball") 2var shadow = document.querySelector(".shadow")

Então instanciamos a Timeline:

1var tl = new TimelineMax()

E adicionamos a primeira animação, movendo a bola por 1/2 segundo para baixo com o método to():

1var tl = new TimelineMax() 2 3tl.to(ball, 0.5, { 4 y: -100, 5})

Em seguida, queremos que ela pareça que atingiu o "chão" rapidamente.

Para isso, em uma fração de segundo, vamos reduzir a altura da bola e alterar levemente o arredondamento das suas bordas inferiores, criando esse efeito de impacto:

1var tl = new TimelineMax() 2 3tl.to(ball, 0.5, { 4 y: 100, 5}).to(ball, 0.1, { 6 scaleY: 0.6, 7 transformOrigin: "center bottom", 8 borderBottomLeftRadius: "40%", 9 borderBottomRightRadius: "40%", 10})
Nota
A propriedade transformOrigin: "center bottom" é adicionada para que a animação da bola impactando o chão fique mais congruente. Por padrão, a animação de scale acontece sempre em direção ao centro, alterando para center bottom, ela acontece em direção ao centro na horizontal e para baixo na vertical.

Animação da sombra

Já temos toda a animação necessária da bola, agora vamos fazer a animação da sombra.

Queremos que a sombra fique maior e mais forte conforme a bola se aproxima do nosso chão imaginário, então vamos fazer isso adicionando mais um to() na linha do tempo.

1var tl = new TimelineMax() 2 3tl.to(ball, 0.5, { 4 y: 100, 5}) 6 .to(ball, 0.1, { 7 scaleY: 0.6, 8 transformOrigin: "center bottom", 9 borderBottomLeftRadius: "40%", 10 borderBottomRightRadius: "40%", 11 }) 12 .to(shadow, 0.5, { 13 width: 90, 14 opacity: 0.7, 15 })

Aqui, a animação da sombra está acontecendo depois da animação da bola. Como a bola sobrepõe a sombra, não conseguimos vê-la.

O efeito desejável é que a animação da sombra aconteça ao mesmo tempo da animação da bola. Uma das formas de fazer isso é usando labels.

Labels

Um label, ou rótulo, é uma marcação na linha do tempo, para que possamos utilizá-lo como referência.

Para ficar mais claro, vamos adicionar um label com o nome "start" no início da Timeline e referenciá-lo na animação da sombra.

1var tl = new TimelineMax() 2 3tl.add("start") 4 .to(ball, 0.5, { 5 y: 100, 6 }) 7 .to(ball, 0.1, { 8 scaleY: 0.6, 9 transformOrigin: "center bottom", 10 borderBottomLeftRadius: "40%", 11 borderBottomRightRadius: "40%", 12 }) 13 .to( 14 shadow, 15 0.5, 16 { 17 width: 90, 18 opacity: 0.7, 19 }, 20 "start" 21 )

O que estamos fazendo é dizer para animação da sombra começar no ponto marcado na linha do tempo como "start".

Dessa maneira, como a animação da sombra tem a mesma duração da animação da bola, ambas começam e terminam ao mesmo tempo.

Imagem da linha do tempo

Repetindo infinitamente com fluidez

Temos toda a animação de que precisamos, agora tudo que temos a fazer é refiná-la.

Primeiro, fazemos a animação repetir infinitamente, para isso, passamos a propriedade repeat: -1 à Timeline no momento em que a instanciamos:

1var tl = new TimelineMax({ repeat: -1 })

Porém, só isso não é o suficiente, pois a animação ainda não funciona em um fluxo contínuo. Ao invés disso, ela está sempre recomeçando do seu estado inicial, dando uma espécie de "salto".

Para fazermos a animação voltar ao estado inicial de forma contínua, passamos também a propriedade yoyo: true:

1var tl = new TimelineMax({ repeat: -1, yoyo: true })

Easing

O último passo restante é adicionar fluidez a animação.

Isso significa aplicar uma função de easing, para que a animação não fique com esse aspecto duro ou não-natural.

A GSAP oferece várias funções de easing já definidas, que você pode ver aqui.

No nosso caso, queremos que a bola pareça estar sofrendo a ação da gravidade, ou seja, ela cai e volta do chão rapidamente, e desacelera quando se aproxima do seu ponto mais alto.

Para aplicarmos esse efeito, vamos usar uma função de easing já disponível na GSAP, chamada Circ.easeIn.

Então, adicionamos essa função na animação da bola e da sombra:

1var tl = new TimelineMax({ repeat: -1, yoyo: true }) 2 3tl.add("start") 4 .to(ball, 0.5, { 5 y: 100, 6 ease: Circ.easeIn, 7 }) 8 .to(ball, 0.1, { 9 scaleY: 0.6, 10 transformOrigin: "center bottom", 11 borderBottomLeftRadius: "40%", 12 borderBottomRightRadius: "40%", 13 }) 14 .to( 15 shadow, 16 0.5, 17 { 18 width: 90, 19 opacity: 0.7, 20 ease: Circ.easeIn, 21 }, 22 "start" 23 )

voilà!

Caso pareça que a bola está grudando no chão antes de quicar, podemos adiantar um pouco a animação de "esmagamento".

Para melhorar o efeito, adicionamos um valor após suas propriedades de animação, nesse caso iremos adicionar "-=0.075". Assim, indicamos que as propriedades da animação devem ser aplicadas um pouco antes na linha do tempo, ou seja, enquanto a animação anterior ainda não terminou!

Dessa forma, deixamos todo o resultado mais suave e natural.

Está criado o nosso loader.

1var ball = document.querySelector(".ball") 2var shadow = document.querySelector(".shadow") 3 4var tl = new TimelineMax({ repeat: -1, yoyo: true }) 5tl.add("start") 6 .to(ball, 0.5, { 7 y: 100, 8 ease: Circ.easeIn, 9 }) 10 .to( 11 ball, 12 0.1, 13 { 14 scaleY: 0.6, 15 transformOrigin: "center bottom", 16 borderBottomLeftRadius: "40%", 17 borderBottomRightRadius: "40%", 18 }, 19 "-=0.075" 20 ) 21 .to( 22 shadow, 23 0.5, 24 { 25 width: 90, 26 opacity: 0.7, 27 ease: Circ.easeIn, 28 }, 29 "start" 30 )

Conclusão

Existem infinitas maneiras de fazer um loader de bola quicando, umas mais simples, outras mais complexas. A ideia desse artigo foi apenas mostrar como funciona a Timeline da GSAP na prática.

Para mais exemplos do uso da Timeline, veja esse link.

Na última parte da série, vamos ver como criar animações com espaços de tempo, acesse aqui.

Compartilhe

Foto de Thiago sorrindo

Autor

Thiago Rossener

Desenvolvedor front-end, filósofo e espiritualista

Sua assinatura não pôde ser validada.
Você fez sua assinatura com sucesso.

Newsletter

Assinando minha newsletter você fica sabendo sempre que eu publicar algo novo, prometo que vai ser só isso.

Comentários