Uma foto minha vestido com o uniforme da Grifinória do Harry Potter

Willian JustenSoftware Engineer

Instrutor na Udemy, escrevo sobre o mundo front end, viagens, vida pessoal e mais.

← Voltar na listagem

#13 - Animando SVG com SMIL

Aprenda a criar animações usando só SVG e nada mais!

Introdução

Enquanto escrevo esse post vou ouvindo Deftones, mudar para um som mais pesado para animar um pouco.

Já faz um tempinho que não escrevia sobre SVG, então vou dar uma quebra nos outros posts e voltar a falar um pouquinho sobre. Se você ainda não conhece SVG sai daqui, dá uma olhadinha na série que eu escrevo nesse blog.

Esse post foi baseado num apanhado de informações de vários cantos:

Animações

Não é de hoje que animações são as queridinhas nos sites e apps, seja pela melhoria em algum aspecto na usabilidade, seja pela beleza que a animação pode proporcionar.

O SVG é tão incrível que permite vários tipos de animações, já falei sobre animações usando css e agora irei falar sobre um tipo específico do SVG, que é a animação usando SMIL.

Mas o que é SMIL? É de comer?

SMIL ou Synchronized Multimedia Integration Language é uma linguagem baseada em XML que permite escrever interações para os elementos. A sua sintaxe é basicamente representada pelos tempos de animações, mudanças dos elementos e inicializações dos comportamentos.

Obs.: funciona em todos os browsers exceto IE caniuse

Por que usar esse treco aí?

A animação em SMIL é declarativa, ou seja, você declara transições e estados para os elementos. A vantagem é que os browsers podem otimizar esse tipo de animação, não pesando tanto na renderização. A grande desvantagem de animações declarativas é que, em geral, elas não são tem tanto poder e não fazem tantas coisas. Eis que o SMIL brilha, ele tem a facilidade e otimização que o CSS permite com o poder de manipulação que só o JS teria.

Como o SMIL é mais poderoso, ele permite animar propriedades que o CSS não conseguiria, como, por exemplo, as formas das Paths.

Outra coisa bastante bacana é que animações feita em SMIL funcionam até mesmo quando o SVG é inserido na tag img! =)

E também conseguimos manipular as animações com eventos! Convencido?

Comandos básicos

Assim como as diferentes tags que o SVG possui para suas formas, ele também possui algumas poucas tags para realizar essas animações, que são:

  • <animate>: permite animar atributos e propriedades num determinado período de tempo.
  • <animateTransform>: usado para animar a transformação dos atributos num período de tempo.
  • <animateMotion: para mover um elemento ao longo de um path.
  • <set>: usado também como um "shorthand" para o animate, é útil para definir valores não numéricos para animação e propriedades, como a propriedade de visibility.

Sintaxe

<animate
  id="myAnim"
  attributeName=" "
  from=" "
  to=" "
  dur=" "
  begin=" "
  fill=" "
  ...
/>

Para o animate temos os principais atributos:

  • attributeName: o atributo do qual iremos alterar, pode ser um fill ou points de um path.
  • from: de onde se inicia.
  • to: para onde vai a animação.
  • dur: a duração da animação.
  • begin: é a "trigger" de inicialização da animação. Podemos colocar como click para dizer que só inicia com um click ou podemos colocar como begin=2s, onde dizemos que a animação só irá começar 2s depois de ter carregado.
  • fill: não confunda com preenchimento, esse atributo serve para dizer se a animação deve parar em seu estado final (freeze) ou a animação ser removida quando alcançar o estado final (remove).
  • repeatCount: como o nome já diz a quantidade de vezes que a animação vai repetir, se quiser que seja infinito, basta usar indefinite.
  • repeatDur: marca o tempo de duração da repetição, a notação é conforme relógio normal, exemplo, 1:30 significa 1 minuto e 30 segundos.

Modos de uso

Existem duas formas de se aplicar animações, que são:

Especificando um target

<rect id="myRect" ... /> <animate xlink:href="#myRect" ... />

Aninhando dentro do elemento

<rect id="myRect" ...>
  <animate ... />
</rect>

Um outro detalhe muito importante é que para cada animate só podemos animar um atributo principal, que é determinado pelo attributeName. Portanto se quisermos fazer 2 tipos diferentes de animação, iremos precisar de 2 elementos animate para cada atributo.

Exemplo

See the Pen by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

<svg width="500" height="100">
  <circle id="orange-circle" r="30" cx="50" cy="50" fill="orange" />

  <animate
    xlink:href="#orange-circle"
    attributeName="cx"
    from="50"
    to="450"
    dur="1s"
    begin="click"
    fill="freeze"
  />
</svg>

No exemplo acima, determinamos que vamos alterar o atributo cx do círculo, ou seja, sua posição no eixo x, passando de 50 para 450, com a duração de 1s após haver o click e tendo animação finalizada pelo freeze ao final da movimentação.

Segue abaixo um exemplo da mudança de posição e de cor, note que utilizamos 2 animate:

See the Pen by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

Controlando animações com keyTimes e values

Assim como nos keyframes do css, no SMIL também podemos criar um conjunto de valores e tempos para criar a animação da forma que desejarmos.

Segue um exemplo utilizando:

values="50; 490; 350; 450" keyTimes="0; 0.5; 0.8; 1"

See the Pen by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

Como pode perceber, no tempo 0 o círculo está na posição 50, aos 0.5 é onde ele vai mais longe, 490, depois ele retorna para 350 e então avança para 450, exatamente como os valores informados. Sempre obedecendo a proporção de uma mudança para um tempo.

Mudando as formas de uma path

Como disse no início do post, a vantagem do SMIL é poder manipular propriedades que o CSS não muda, como, por exemplo a forma de um path.

Vamos pensar num primeiro exemplo, onde queremos transformar um quadrado em um círculo.

See the Pen by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

Nós iremos trabalhar no attributeName=d, que é onde desenhamos a path e teremos 2 passos, from, que contém a forma de um quadrado e o to, que contém a forma de um círculo, definimos um tempo para a animação ocorrer e pronto, a mágica acontece.

Agora vamos pensar numa situação em que eu tenho um quadrado virando um triângulo e este virando um círculo, ou seja, 3 etapas. Para trabalhar com mais de uma etapa, basta definir mais valores dentro de values e casos queiramos mudar o tempo de acordo com a mudança, podemos usar o keyTimes. Segue um exemplo dessa transição:

See the Pen by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

Mas e se eu quisesse além de mudar os 3 visuais, também quisesse mudar de cor? Basta adicionar mais um animate, passando os values do attributeName=fill. Segue um exemplo colorido:

See the Pen by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

Aplicação prática em UX

Pow Willian, isso tudo aí é muito legal, muito maneiro, mas não vejo utilidade nenhuma nisso aí. Onde eu poderia aplicar um treco desses no meu site?

Podemos, por exemplo, aplicar uma mudança de um ícone para dar um feedback para o usuário. Segue um botão seguindo esse tipo de interação:

See the Pen by Willian Justen de Vasconcellos (@willianjusten) on CodePen.

As animações realizadas para o botão acima ficam separadas em:

  • Transformar no check
  • Mudar para cor verde
  • Transformar na estrela
  • Mudar para cor amarela

Para cada uma dessas animações utilizamos a tag animate sempre definindo o to, que significa para onde estamos transformando. O JS utilizado no exemplo é só para adicionar o textinho (salvar -> salvo!) e iniciar as animações. Mas lembramos que podemos utilizar o begin=click para fazer esse tipo de trigger para inicialização.

Conclusão

Bom pessoal, esse post serviu para mostrar mais uma habilidade exclusiva e super interessante que o SVG possui. Lembre-se que animações para conseguir melhorar a usabilidade do usuário são sempre boas adições e o SVG pode te prover isso muito bem. Existem muitas coisas sobre SMIL, portanto não fique somente neste post e busque ainda mais informação, qualquer coisa, também pergunte nos comentários.