Pular para o conteúdo principal

GOOD MOOD parte 2: animando as letras

· Leitura de 9 minutos

Na segunda parte, animo as letras e defino suas posições e cores.


Animando as letras

Atributos do elemento animate

attributeName

Nome do atributo que mudará durante a animação, o atributo d no caso desta animação.

values

Sequência de valores usada no decorrer da animação. No caso desta animação, são 3 valores do atributo d.

Para as letras da primeira fileira: versão normal, versão esticada e versão normal novamente. Na segunda fileira: versão esticada, versão normal e versão esticada novamente.

calcMode

Modo de interpolação (processo que calcula os valores intermediários da animação), que é spline. Permite usar curvas de Bézier para definir a função de tempo, possibilitando transições suaves.

keyTimes

Sequência de valores que define o ritmo da animação, cada valor fica entre 0 e 1. Com calcMode spline, para cada valor de values, deve existir um valor de keyTimes.

No caso desta animação, 0; 0.5; 1. Ou seja, o primeiro valor de values é usado no início da animação, o segundo valor é usado na metade da animação, e o terceiro valor é usado no fim da animação.

keySplines

Sequência de valores que define as curvas de Bézier (x1, y1, x2, y2) usadas nos intervalos entre os valores do atributo keyTimes.

No caso desta animação, 0.45, 0.05, 0.55, 0.95; 0.45, 0.05, 0.55, 0.95 (duas curvas iguais). Ou seja, entre 0; 0.5 o primeiro valor é usado, e entre 0.5; 1 o segundo valor é usado.

begin

Define quando a animação deve começar. Usei para atrasar o início da animação de cada coluna para criar o movimento de onda.

dur

A duração da animação, que é 1s.

repeatCount

Número de repetições, que é indefinite (repete-se indefinidamente).

Atributos desta animação

Deixei o atributo d do elemento path vazio, visto que ele é definido no atributo values do elemento animate. Os únicos atributos do elemento animate que mudam de uma letra para outra são values e begin, os demais atributos têm o mesmo valor em todas as letras.

<svg viewBox="0 0 10 20">  <path d="">    <animate      attributeName="d"      begin="valor baseado na coluna"      dur="1s"      repeatCount="indefinite"      calcMode="spline"      keySplines="0.45, 0.05, 0.55, 0.95; 0.45, 0.05, 0.55, 0.95"      keyTimes="0; 0.5; 1"      values="desenho de letra; desenho de letra; desenho de letra"    />  </path></svg>

Nas visualizações seguintes não defini o atributo begin, porque ainda estava lidando individualmente com cada letra. Mostro a posição final na seção Definindo as posições.

Nestas seções usei um viewBox que comporta apenas uma letra:

<svg viewBox="0 0 10 20" width="200">  <!-- demais elementos entrarão aqui --></svg>

Primeira fileira

info

Em cada visualização, omiti os elementos svg e path que se encontrariam em volta do elemento animate, assim como seus demais atributos, para manter o código conciso.

<animate  values="    versão normal;    versão esticada;    versão normal  "/>

Letra G

<animate  values="    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,4.6 L6,4.6 L6,4 C6,3 4,3 4,4 L4,6 C4,7 6,7 6,6 L5,6 L5,5 L10,5 L10,10 L7,10 L6.6,9 Q6,10 4,10 Q0,10 0,6z;    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,14.6 L6,14.6 L6,4 C6,3 4,3 4,4 L4,16 C4,17 6,17 6,16 L5,16 L5,15 L10,15 L10,20 L7,20 L6.6,19 Q6,20 4,20 Q0,20 0,16z;    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,4.6 L6,4.6 L6,4 C6,3 4,3 4,4 L4,6 C4,7 6,7 6,6 L5,6 L5,5 L10,5 L10,10 L7,10 L6.6,9 Q6,10 4,10 Q0,10 0,6z  "/>

Letra O

<animate  values="    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,6 Q10,10 6,10 L4,10 Q0,10 0,6 L4,6 C4,7 6,7 6,6 L6,4 C6,3 4,3 4,4 L4,6 L0,6z;    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,16 Q10,20 6,20 L4,20 Q0,20 0,16 L4,16 C4,17 6,17 6,16 L6,4 C6,3 4,3 4,4 L4,16 L0,16z;    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,6 Q10,10 6,10 L4,10 Q0,10 0,6 L4,6 C4,7 6,7 6,6 L6,4 C6,3 4,3 4,4 L4,6 L0,6z  "/>

Letra D

<animate  values="    M0,0 L6,0 Q10,0 10,4 L10,6 Q10,10 6,10 L0,10 L0,7 L4,7 Q6,7 6,6 L6,4 Q6,3 4,3 L4,7 L0,7z;    M0,0 L6,0 Q10,0 10,4 L10,16 Q10,20 6,20 L0,20 L0,17 L4,17 Q6,17 6,16 L6,4 Q6,3 4,3 L4,17 L0,17z;    M0,0 L6,0 Q10,0 10,4 L10,6 Q10,10 6,10 L0,10 L0,7 L4,7 Q6,7 6,6 L6,4 Q6,3 4,3 L4,7 L0,7z  "/>

Segunda fileira

info

Em cada visualização, omiti os elementos svg e path que se encontrariam em volta do elemento animate, assim como seus demais atributos, para manter o código conciso.

<animate  values="    versão esticada;    versão normal;    versão esticada  "/>

Letra M

<animate  values="    M0,0 L4,0 L5,6 L6,0 L10,0 L10,20 L7,20 L7,7 L6,20 L4,20 L3,7 L3,20 L0,20z;    M0,10 L4,10 L5,14 L6,10 L10,10 L10,20 L7,20 L7,15 L6,20 L4,20 L3,15 L3,20 L0,20z;    M0,0 L4,0 L5,6 L6,0 L10,0 L10,20 L7,20 L7,7 L6,20 L4,20 L3,7 L3,20 L0,20z  "/>

Letra O

<animate  values="    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,16 Q10,20 6,20 L4,20 Q0,20 0,16 L4,16 C4,17 6,17 6,16 L6,4 C6,3 4,3 4,4 L4,16 L0,16z;    M0,14 Q0,10 4,10 L6,10 Q10,10 10,14 L10,16 Q10,20 6,20 L4,20 Q0,20 0,16 L4,16 C4,17 6,17 6,16 L6,14 C6,13 4,13 4,14 L4,16 L0,16z;    M0,4 Q0,0 4,0 L6,0 Q10,0 10,4 L10,16 Q10,20 6,20 L4,20 Q0,20 0,16 L4,16 C4,17 6,17 6,16 L6,4 C6,3 4,3 4,4 L4,16 L0,16z  "/>

Letra D

<animate  values="    M0,0 L6,0 Q10,0 10,4 L10,16 Q10,20 6,20 L0,20 L0,17 L4,17 Q6,17 6,16 L6,4 Q6,3 4,3 L4,17 L0,17z;    M0,10 L6,10 Q10,10 10,14 L10,16 Q10,20 6,20 L0,20 L0,17 L4,17 Q6,17 6,16 L6,14 Q6,13 4,13 L4,17 L0,17z;    M0,0 L6,0 Q10,0 10,4 L10,16 Q10,20 6,20 L0,20 L0,17 L4,17 Q6,17 6,16 L6,4 Q6,3 4,3 L4,17 L0,17z  "/>

Definindo as posições

Elementos defs e use

Defini o atributo id de cada elemento path e os coloquei dentro do elemento defs, para que depois pudesse referenciá-los com elementos use pelo atributo href.

Com o elemento use, defini a posição de cada letra com os atributos x e y, seguindo a grade. Pus um número no fim do valor do atributo id das letras que se repetiam, pois eles devem ser únicos.

<!--  omiti os atributos dos elementos animate  para manter o código conciso --><svg viewBox="0 0 63 51">  <defs>    <!-- primeira fileira -->    <path d="" id="letter-g"><animate /></path>    <path d="" id="letter-o-1"><animate /></path>    <path d="" id="letter-o-2"><animate /></path>    <path d="" id="letter-d-1"><animate /></path>    <!-- segunda fileira -->    <path d="" id="letter-m"><animate /></path>    <path d="" id="letter-o-3"><animate /></path>    <path d="" id="letter-o-4"><animate /></path>    <path d="" id="letter-d-2"><animate /></path>  </defs>  <!-- primeira fileira -->  <use href="#letter-g" x="10" y="10" />  <use href="#letter-o-1" x="21" y="10" />  <use href="#letter-o-2" x="32" y="10" />  <use href="#letter-d-1" x="43" y="10" />  <!-- segunda fileira -->  <use href="#letter-m" x="10" y="21" />  <use href="#letter-o-3" x="21" y="21" />  <use href="#letter-o-4" x="32" y="21" />  <use href="#letter-d-2" x="43" y="21" /></svg>

Definindo o atributo begin

Seguindo a animação original, quando a primeira coluna está esticada para cima, a última coluna está esticada para baixo. Como a animação tem 1s, defini que a primeira coluna tem o atributo begin como -1 (valores negativos fazem com que não exista delay ao iniciar a animação), e a última coluna como -0.5. Ou seja, quando a primeira coluna completa um clico de animação, a última coluna completa metade de um ciclo.

Para obter o valor do atributo begin das demais colunas, calculei o intervalo de tempo que deveria existir entre o início da animação de cada uma das 4 colunas: 0.5 / 3 ≈ 0.1666. Com isso, calculei o valor do atributo begin de cada coluna:

  • Primeira coluna: -1
  • Segunda coluna: -1 + 0.1666 ≈ -0.8333
  • Terceira coluna: -0.8333 + 0.1666 ≈ -0.6666
  • Quarta coluna: -0.6666 + 0.1666 ≈ -0.5
<!--  omiti os demais atributos dos elementos animate  para manter o código conciso --><svg viewBox="0 0 63 51">  <defs>    <!-- primeira fileira -->    <path d="" id="letter-g">      <animate begin="-1" />    </path>    <path d="" id="letter-o-1">      <animate begin="-0.8333" />    </path>    <path d="" id="letter-o-2">      <animate begin="-0.6666" />    </path>    <path d="" id="letter-d-1">      <animate begin="-0.5" />    </path>    <!-- segunda fileira -->    <path d="" id="letter-m">      <animate begin="-1" />    </path>    <path d="" id="letter-o-3">      <animate begin="-0.8333" />    </path>    <path d="" id="letter-o-4">      <animate begin="-0.6666" />    </path>    <path d="" id="letter-d-2">      <animate begin="-0.5" />    </path>  </defs>  <!-- primeira fileira -->  <use href="#letter-g" x="10" y="10" />  <use href="#letter-o-1" x="21" y="10" />  <use href="#letter-o-2" x="32" y="10" />  <use href="#letter-d-1" x="43" y="10" />  <!-- segunda fileira -->  <use href="#letter-m" x="10" y="21" />  <use href="#letter-o-3" x="21" y="21" />  <use href="#letter-o-4" x="32" y="21" />  <use href="#letter-d-2" x="43" y="21" /></svg>

Definindo cores

Defini as cores de cada letra no elemento use, e a cor do plano de fundo com um elemento rect. A ordem dos elementos importa, o rect deve ser desenhado antes das letras, do contrário, o rect seria desenhado por cima das letras.

<div class="wrapper">  <div class="container">    <svg viewBox="0 0 63 51">      <defs>        <!--          omiti o conteúdo do elemento defs          para manter o código conciso         -->      </defs>      <!-- fundo preto -->      <rect width="63" height="51" fill="#000" />      <!-- primeira fileira -->      <use href="#letter-g" x="10" y="10" fill="#FFFFFF" />      <use href="#letter-o-1" x="21" y="10" fill="#FFFFFF" />      <use href="#letter-o-2" x="32" y="10" fill="#FFFFFF" />      <use href="#letter-d-1" x="43" y="10" fill="#FFFFFF" />      <!-- segunda fileira -->      <use href="#letter-m" x="10" y="21" fill="#FFB200" />      <use href="#letter-o-3" x="21" y="21" fill="#006BF5" />      <use href="#letter-o-4" x="32" y="21" fill="#FD002D" />      <use href="#letter-d-2" x="43" y="21" fill="#FF769F" />    </svg>  </div></div>

Para centralizar a animação, adicionei CSS.

/* reset simples */*,*::before,*::after {  box-sizing: border-box;  margin: 0;  padding: 0;}/* o wrapper tem a altura do viewport */.wrapper {  display: flex;  min-height: 100vh;}/* a animação fica no centro da tela */.container {  margin: auto;  width: 800px;  max-width: 100%;}

Conclusão

Tendo a animação feita e as cores definidas, segui para os filtros: GOOD MOOD parte 3: aplicando filtros.

Leitura recomendada