Postado dia

E ae pessoas! Mês passado publiquei aqui no blog um tutorial de como animar SVG usando a propriedade CSS “transition”. Agora eu vou ensinar um outro tipo de animação de SVG usando SMIL: Synchronized Multimedia Integration Language (em português, Linguagem de Integração de Multimídia Sincronizada).

SMIL foi originalmente criado como uma linguagem declarativa capaz de organizar apresentações multimídia de arquivos na web, indicando posição, quando tocar, animações, quando realizar uma transição, etc, tudo a partir de um arquivo com extensão .smil que usa estrutura similar ao XML. Já no SVG, algumas tags de animação do SMIL foram embutidas nele, permitindo animar os elementos do SVG através dessas tags.

Neste tutorial, ensinarei como usar essas tags criando uma simples animação parecida com a de preloaders de sites. Você pode ver o que faremos abaixo. Partiu!

1. Preparando o SVG no Illustrator

Vamos fazer algo extremamente simples no Illustrator. Para isso, crie um arquivo novo com uma área de 600 x 600 px. Depois desenhe um círculo (ferramenta Elipse, ou use o atalho L) de 420 pixels de diâmetro sem contorno e alinhe no centro da prancheta (Shift + F7 para chamar a janela Alinhar).

Alinhamento centralizado na prancheta pela janela Alinhar

1 – Alinhamento horizontal centralizado, 2 – Alinhamento vertical centralizado, 3 – Clique e selecione “Alinhar à prancheta”

Agora selecione o círculo com a ferramenta Seleção Direta (atalho A) para exibir todos os 4 pontos âncoras do círculo. Agora selecione a ferramenta Tesoura (atalho C), tomando cuidado para não tirar a seleção do círculo, e clique no ponto superior do círculo. Isso irá cortar o caminho do círculo, definindo um começo e fim para ele.

Depois desenhe o outro círculo novo de 152 pixels de diâmetro, selecione-o e na área Transformar, selecione o ponto de referência central para definir seu eixo de posição no exato meio do círculo, e nos campos X e Y, deixe o valor 0. Isso irá fazer o círculo ficar no canto superior esquerdo da prancheta, com uma parte do círculo para fora dela.

Janela Transformar

1 – Selecione o ponto de referência do meio, 2 – Deixe as posições X e Y igual a 0 px

Agora, com esse círculo novo selecionado, aperte Ctrl + C (ou Command + C no Mac) e depois aperte Ctrl + F (ou Command +F no Mac) para copiar e colar o círculo exatamente na mesma posição do círculo selecionado. Agora temos dois círculos idênticos, mas agora você precisa repetir isso mais 10 vezes, totalizando 12 círculos no canto da prancheta, um sobre o outro. Explicarei depois porque 12 círculos e não 6, como visto na animação no começo deste post.

O SVG final… Estranho né?

O SVG final… Estranho né?

Agora salve o arquivo como SVG, mas quando abrir a janela Opções de SVG, clique no botão “Código SVG…” para abrir a estrutura XML do SVG. Aqui você precisará fazer uma limpeza. Na tag <svg>, deixe os atributos version, xmlns e viewBox, tirando o resto dos atributos. Pode remover a tag <?xml ?> e o comentário <!-- -->. O SVG vai ficar assim:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
  <path d="M301,91c116,0,210,94,210,210s-94,210-210,210S91,417,91,301S185,91,301,91"/>
  <circle cx="0" cy="0" r="76"></circle>  
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>  
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
  <circle cx="0" cy="0" r="76"></circle>
</svg>

Agora copie esse XML e cole dentro do seu HTML.

2. Definindo o estado inicial do SVG

Agora vamos começar a preparar a estrutura para a animação. Para isso, vamos mudar a estrutura do SVG. Ele vai precisar ficar assim:

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 600 600">
  <path d="M301,91c116,0,210,94,210,210s-94,210-210,210S91,417,91,301S185,91,301,91" id="motionPath" fill="none" stroke="none"/>
  <circle cx="300" cy="300" r="76" id="c1" class="c"></circle>  
  <circle cx="0" cy="0" r="76" id="c1r" class="c2"></circle>
  <circle cx="300" cy="300" r="76" id="c2" class="c"></circle>  
  <circle cx="0" cy="0" r="76" id="c2r" class="c2"></circle>
  <circle cx="300" cy="300" r="76" id="c3" class="c"></circle>  
  <circle cx="0" cy="0" r="76" id="c3r" class="c2"></circle>
  <circle cx="300" cy="300" r="76" id="c4" class="c"></circle>  
  <circle cx="0" cy="0" r="76" id="c4r" class="c2"></circle>
  <circle cx="300" cy="300" r="76" id="c5" class="c"></circle>  
  <circle cx="0" cy="0" r="76" id="c5r" class="c2"></circle>
  <circle cx="300" cy="300" r="76" id="c6" class="c"></circle>  
  <circle cx="0" cy="0" r="76" id="c6r" class="c2"></circle>
</svg>

Começando pela tag <path>, aonde eu inseri um atributo "id" com o valor “motionPath”. Sim, usaremos ele como um caminho pela qual a animação irá se movimentar. Junto com isso, tirei tanto o preenchimento (fill="none") quanto a borda (stroke="none") pois não queremos que o caminho seja algo visível.

Quanto aos círculos menores, foi definido um atributo "id" para cada um, com a letra “c” + um número (lembre-se que ids são únicas e não podem se repetir ao longo do documento). Porém metade deles têm um “r” depois do número. No geral, a ordem seguiria assim: c1, c1r, c2, c2r… Além das “id”, defini para os elementos com “id” sem o final “r”, a classe “c”. Para os outros, definimos a classe “c2”. A ideia dessas duas classes e as ids são:

  • c: elementos com esta classe cuidarão da animação do elemento surgindo até se posicionar em cima do caminho “motionPath”;
  • c2: elementos com esta classe irão percorrer o “motionPath” e realizar a animação de cores. As “id” destes círculos apresentam um “r” no final justamente para indicar o efeito de rotação.

Quando se trata de animação SMIL, é importante aplicar um id em todos os elementos que desenham ou animam algo no SVG pois é através deles que aplicamos as animações.

Para os elementos com “id” sem o final “r”, definimos um posicionamento de 300px no eixo X e 300px no eixo Y para metade dos círculos, pois queremos que o círculo surja do meio do SVG. Para os outros, deixamos o posicionamento original mesmo.

Com toda essa organização, definimos dois grupos, cada um formado por 6 círculos. O motivo disso é que precisamos alinhar o estado inicial dos círculos no meio do SVG, mas também precisamos que ele sigam o caminho “motionPath”, mas para que ele siga o caminho corretamente, precisamos que ele esteja posicionado nas coordenadas 0,0. Então para que os dois casos funcionem, duplicamos os círculos e através das animações, um vai trocar pelo outro para que pareçam ser o mesmo círculo.

CSS

Agora vamos definir o CSS do SVG:

svg{width: 200px; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);}
svg *{stroke-linecap: round;}
svg circle{stroke-width: 8px; stroke: #000; fill: #000; stroke-dasharray: 600;}
.c{fill-opacity: 0; stroke-dashoffset: 600; opacity: 1;}
.c2{stroke-dashoffset: 0; opacity: 0;}

Por linha:

svg{width: 200px; position: absolute; top: 50%; left: 50%; transform: translate(-50%,-50%);}

Aqui definimos uma largura fixa para o SVG de 200px (width: 200px;), além de deixarmos com uma posição absoluta (position: absolute;), permitindo alinhá-lo no centro da página (top: 50%; left: 50%;), corrigindo a posição com uma transformação (transform: translate(-50%,-50%);).

svg *{stroke-linecap: round;}

Aqui apontamos todos os elementos dentro da tag <svg> e mandamos ele arredondar a pontas dos contornos de todos os elementos. Porém isso é só estética. Outra aparência que você pode aplicar às pontas são as ilustradas abaixo, porém isso não vai influenciar muito no design.

svg circle{stroke-width: 8px; stroke: #000; fill: #000; stroke-dasharray: 478;}

Já nessa linha, definimos a espessura do contorno para 8px e a cor da espessura para preto (stroke-width: 8px; stroke: #000;). O preenchimento inicial também será preto (fill: #000;) e o tamanho do espaço entre os tracejados será igual a 478 para que o contorno fique escondido inicialmente.

Agora como que chegamos ao valor de 478? Em outro tutorial aonde aprendemos a animar SVG usando CSS transition, usamos javascript para descobrir o valor de “stroke-dasharray”. Como aqui não usaremos isso, e estamos tratando de um círculo, há uma antiga fórmula matemática que usaremos: a fórmula de circunferência.

C = πd

Circunferência é igual ao PI (3,14) multiplicado pelo diâmetro. Agora, olhando as tags <circle>, foi definido em todas elas o atributo “r”, que define o raio do círculo. Isso foi gerado pelo Illustrator.

Se do centro de um círculo até a sua extremidade é a distância do raio, e o diâmetro é a extensão de um lado ao outro do círculo passando pelo seu centro, então já sabemos que o diâmetro é igual ao raio multiplicado por 2. Ou seja: 76 x 2 = 152.

Então, podemos pegar o valor da circunferência: C = 3,14 x 152 = 477,28. Arredondando para cima: 478. Lembre-se que para formas mais complexas, não tem outro jeito a não ser usar javascript… ou ir no chutômetro.

.c{fill-opacity: 0; stroke-dashoffset: 478; opacity: 1;}

Aqui apontamos os elementos que tem a primeira classe, “c”, que definimos nos <circle>, definindo o estado inicial deles para espessura totalmente transparente (fill-opacity: 0;), o ponto em que o traçado começará a ser desenhado usando o valor da circunferência (stroke-dashoffset: 478;) e o nível de transparência para opaco (opacity: 1;).

.c2{stroke-dashoffset: 0; opacity: 0;}

Já para os elementos que tem a segunda classe, “c2”, definimos o estado inicial do ponto em que o traçado começará a ser desenhado para 0 (stroke-dashoffset: 0;), já que os elementos “c2” serão aqueles que se seguirão o caminho e surgirão assim que o outro círculo próximo com classe “c” se posicionar para seguir o caminho “motionPath”. E seu nível de transparência será total (opacity: 0;).

3. Animando um círculo

Agora que definimos a estrutura inicial, podemos animar! Vamos começar pelo primeiro círculo, que engloba os elementos de ids “c1” e “c1r”. Dentro do elemento “c1”, aplique as seguintes tags:

<animate id="c1a1" attributeType="CSS" attributeName="stroke-dashoffset" from="478" to="0" dur="0.5s" repeatCount="1" fill="freeze"/>
<animate id="c1a2" attributeType="CSS" attributeName="fill-opacity" from="0" to="1" dur="0.25s" repeatCount="1" fill="freeze" begin="c1a1.end"/>
<animate id="c1a3" attributeName="cy" from="300" to="91" dur="0.5s" repeatCount="1" fill="freeze" begin="c1a2.end" keySplines=".42 0 .58 1" keyTimes="0;1" calcMode="spline"/>
<animate id="c1a4" attributeType="CSS" attributeName="opacity" from="1" to="0" dur="0.001s" repeatCount="1" fill="freeze" begin="c1a3.end"/>

As tags <animate> são as responsáveis por animar o círculo. Aqui, a animação alterará quatro propriedades do círculo: desenho do traço, transparência do preenchimento, posicionamento e transparência geral. Foram todas ordenadas na ordem que vão ser animadas. Então vamos analisar linha por linha:

<animate id="c1a1" attributeType="CSS" attributeName="stroke-dashoffset" from="478" to="0" dur="0.5s" repeatCount="1" fill="freeze"/>

Como dito, é importante colocar "id" em todos os elementos dentro do SVG que desenham ou animam algo. Aqui aplicamos a id “c1a1”, “a” de animação, sabendo que as tags estão organizadas na ordem em que a animação ocorrerá.

Nesta etapa, animaremos uma propriedade CSS, então precisamos definir o atributo "attributeType" com o valor “CSS”. Depois indicamos qual propriedade CSS será animada usando o atributo "attributeName", no caso será a propriedade “stroke-dashoffset”.

Depois, precisamos definir o valor inicial e final da animação usando os atributos "from" (de) e "to" (para). Aqui, queremos que o traço seja desenhado, então aplicamos o valor da circunferência que obtivemos anteriormente em “from” para que o traço esteja sumido inicialmente, influenciado pelo “stroke-dasharray” que aplicamos via CSS, e em “to”, aplicamos 0 para que o traço apareça. Se quiser, você pode usar o atributo "values" com o valor “478;0”, que será o mesmo que usar “from” e “to”.

Depois definimos a duração da animação em segundos usando o atributo "dur", definindo o tempo em segundos usando a unidade “s”. No caso, definimos uma duração de meio segundo (0.5s). Também definimos o tanto de vezes que a animação irá repetir usando o atributo "repeatCount". Como não queremos repetição alguma, definimos o valor igual a 1. E por fim, a propriedade "fill" define o que acontecerá quando esta animação específica terminar. O valor “freeze” indica que a animação congelará no seu último quadro, que é o que queremos.

<animate id="c1a2" attributeType="CSS" attributeName="fill-opacity" from="0" to="1" dur="0.25s" repeatCount="1" fill="freeze" begin="c1a1.end"/>

Semelhante a linha anterior, definimos uma “id” igual a “c1a2”, apontamos a propriedade CSS “fill-opacity” e a animamos do valor 0 ao valor 1. Deixamos sem repetição e congelamento no quadro final. Porém aqui entra um atributo novo: “begin”.

Esse atributo define quando a animação em questão irá começar a rodar. Aqui você pode usar 5 tipos de valores:

  • Unidades de tempo: pode ser em segundos (“s”), milésimos de segundos (“ms”), minutos (“min”) ou horas (“h”), e é relativo a quando o SVG termina de carregar (exemplo: 5.5s);
  • Base de sincronismo: indica o começo ou término de outra animação apropriadamente identificada (exemplo: c1a1.begin, aponta para o momento em que o elemento com id “c1a1” começa a animar, definido no atributo “begin”), podendo ainda adicionar um tempo relativo a essa base (exemplo: c1a1.begin + 2s, indicada para o momento 2 segundos após o inicio da animação “c1a1”);
  • Evento: indica um evento específico (click, focusin, mouseup, DOMNodeRemove, beginEvent, etc), fazendo a animação rodar assim que este evento for disparado;
  • Repetição: indica uma repetição tendo como base uma animação já definida. Por exemplo: você define uma animação de um quadrado em movimento que dura 5 segundos com o id “meuLoop” e define o atributo “repeatCount” com valor igual a 3. Em uma tag <set>, semelhante a <animate>, você define o atributo “begin” com o valor “meuLoop.repeat(1)”. Isso quer dizer que o segundo loop do “repeatCount” (conta do zero), o <set> com begin="meuLoop.repeat(1)" irá aplicar suas definições de animação dentro da animação “meuLoop” somente no segundo loop;
  • Tecla: indica um botão do teclado listados aqui. Pode ser, por exemplo, qualquer letra escrito em maiúsculo (accessKey(A)), o nome de uma tecla específica (accessKey(PageDown)), ou um unicode (accessKey(U+0041), que é equivalente a accessKey(A));

NOTA: o atributo “begin” pode ter dois valores. No caso do exemplo de uso de loops citado no tipo “Repetição”, você pode não definir o atributo “fill”, e aplicar o atributo begin="0s;meuLoop.end". Isso irá fazer a animação recomeçar assim que terminar.

Voltando ao tutorial, indicamos para esta animação começar assim que a animação com id igual a “c1a1” terminar (c1a1.end).

<animate id="c1a3" attributeName="cy" from="300" to="91" dur="0.5s" repeatCount="1" fill="freeze" begin="c1a2.end" keySplines=".42 0 .58 1" keyTimes="0;1" calcMode="spline"/>

Aqui as coisas mudam um pouco. Como iremos animar um atributo do círculo, só o atributo “attributeName” já basta. Ele aponta para o atributo “cy” para que ele anime a posição Y do círculo, indo de 300px para 91px. Lembre-se que é usando o centro do círculo como ponto de referência para posicionamento.

Então para saber a posição Y aonde o círculo tem que ir, temos que saber a posição Y do caminho. Como definimos o começo e o fim do caminho no mesmo lugar pelo Illustrator, podemos pegar as coordenadas X e Y dele pelo atributo “d” da tag <path>. O valor do atributo começa com “M301,91”. No caso, “301,90” seria as coordenadas X e Y. 91 é o valor que queremos para o atributo “to”.

Além das propriedades já exploradas nas linhas anteriores (notando sempre os valores de “id” que definimos e os valores dos atributos “begin”), aqui entra três novos atributos:

  • calcMode: define o ritmo da animação, podendo ser:
    • “linear”: interpolação simples;
    • “paced”: interpolação simples que ignora as animações intermediárias entre os valores do atributo “values” e então divide o tempo de acordo para criar uma animação sem mudança de velocidade entre todos os valores, ignorando então os valores do atributo “keyTimes”. Se for usado os atributos “from” e “to”, ou o atributo “values” só com dois valores, a diferença entre “linear” e “paced” será imperceptível;
    • “discrete”: ignora qualquer animação intermediária, pulando de um passo a outro da animação definidos em “values” ou “from” e “to”, mas respeitando o tempo em “keyTimes”, desde que o primeiro tempo definido seja sempre 0;
    • “spline”: interpolação avançada que calcula ritmo baseado nas coordenadas X e Y dos pontos 1 e 2 de uma curva de Bézier cúbica. Para isso, a animação precisa saber os valores desses dois pontos através do atributo “keySplines”.
  • keyTimes: define os pontos de mudança durante a animação, sendo que o ponto na animação é indicado usando um valor entre 0 e 1. Então se a animação têm 0.5 segundos de duração, 1 indica exatamente 0.5 segundos de tempo, enquanto 0.5 indica 0.25 segundos;
  • keySplines: define a posição X e Y dos pontos 1 e 2 da curva de Bézier cúbica utilizada por calcMode="spline". Os valores devem ser separados por espaços. Um bom site para obter as coordenadas desejadas é o cubic-bezer.com. Os “key splines” seriam os pontos azul e rosa que você move no gráfico. Os valores serão os que estiverem escritos no título da página, dentro dos parênteses.
<animate id="c1a4" attributeType="CSS" attributeName="opacity" from="1" to="0" dur="0.001s" repeatCount="1" fill="freeze" begin="c1a3.end"/>

Aqui é igual a linha 2, mas note que a duração da animação foi definida igual a 0.001s, ou seja, um milésimo de segundo. Isso é porque aqui queremos que o círculo suma enquanto o outro círculo apareça para seguir o caminho “motionPath”. Então a opacidade do círculo mudará num piscar de olhos.

Agora dentro do círculo “c1r”, cole a seguinte linha:

<animate attributeType="CSS" attributeName="opacity" from="0" to="1" dur="0.001s" repeatCount="1" fill="freeze" begin="c1a4.begin"/>

Igual a linha 4 do código dentro do círculo “c1”, ele vai animar a opacidade em um piscar de olhos, mas aqui será ao contrário, fazendo o círculo surgir. Aqui definimos o atributo “begin” com o valor “c1a4.begin”, indicando o atributo “begin” da tag <animate> com “id” igual a “c1a4”, que seria a última tag de animação dentro de “c1”, que define quando o “c1” some e quando o “c1r” aparece.

Agora, depois da tag </circle> do “c1r”, cole a seguintes linhas:

<animateMotion xlink:href="#c1r" dur="6s" begin="c1a4.begin" repeatCount="indefinite">
<mpath xlink:href="#motionPath" />
</animateMotion>

A tag <animateMotion> será a responsável por fazer o círculo “c1r” andar sobre o caminho definido em “motionPath”. Para isso, o atributo "xlink:href" deve apontar para o círculo usando o #, que indica uma id. Igual ao <animate> do “c1r”, o atributo "begin" deve ter o valor de “c1a4.begin”. Também queremos que o círculo percorra o caminho infinitamente, então definimos o atributo “repeatCount” com o valor “indefinite”, que indica algo indefinível.

Dentro de <animateMotion>, a tag <mpath> indica o caminho a ser seguido. No caso, apontamos para o id “motionPath” do mesmo jeito que apontamos para o id “c1r” na linha anterior.

Todo esta parte irá resultar nisto:

4. Animando os outros círculos

Agora precisamos aplicar o que fizemos no “c1” e “c1r” nos outros círculos. Mas para que a animação fique certinha, precisamos fazer as animações começarem com um tempo diferente.

O que temos do primeiro círculo é isso:

  <circle cx="300" cy="300" r="76" id="c1" class="c">
      <animate id="c1a1" attributeType="CSS" attributeName="stroke-dashoffset" from="478" to="0" dur="0.5s" repeatCount="1" fill="freeze"/>
      <animate id="c1a2" attributeType="CSS" attributeName="fill-opacity" from="0" to="1" dur="0.25s" repeatCount="1" fill="freeze" begin="c1a1.end"/>
    <animate id="c1a3" attributeName="cy" from="300" to="91" dur="0.5s" repeatCount="1" fill="freeze" begin="c1a2.end" keySplines=".42 0 .58 1" keyTimes="0;1" calcMode="spline"/>
    <animate id="c1a4" attributeType="CSS" attributeName="opacity" from="1" to="0" dur="0.001s" repeatCount="1" fill="freeze" begin="c1a3.end"/>
  </circle>
  <circle cx="0" cy="0" r="76" id="c1r" class="c2">
    <animate attributeType="CSS" attributeName="opacity" from="0" to="1" dur="0.001s" repeatCount="1" fill="freeze" begin="c1a4.begin"/>
  </circle>
  <animateMotion xlink:href="#c1r" dur="6s" begin="c1a4.begin" repeatCount="indefinite">
    <mpath xlink:href="#motionPath" />
  </animateMotion>

Já no segundo círculo, teremos que deixar assim:

  <circle cx="300" cy="300" r="76" id="c2" class="c">
      <animate id="c2a1" attributeType="CSS" attributeName="stroke-dashoffset" from="478" to="0" dur="0.5s" repeatCount="1" fill="freeze" begin="c1a1.begin + 1s"/>
      <animate id="c2a2" attributeType="CSS" attributeName="fill-opacity" from="0" to="1" dur="0.25s" repeatCount="1" fill="freeze" begin="c2a1.end"/>
    <animate id="c2a3" attributeName="cy" from="300" to="91" dur="0.5s" repeatCount="1" fill="freeze" begin="c2a2.end" keySplines=".42 0 .58 1" keyTimes="0;1" calcMode="spline"/>
    <animate id="c2a4" attributeType="CSS" attributeName="opacity" from="1" to="0" dur="0.001s" repeatCount="1" fill="freeze" begin="c2a3.end"/>
  </circle>
  <circle cx="0" cy="0" r="76" id="c2r" class="c2">
    <animate attributeType="CSS" attributeName="opacity" from="0" to="1" dur="0.001s" repeatCount="1" fill="freeze" begin="c2a4.begin"/>
  </circle>
  <animateMotion xlink:href="#c2r" dur="6s" begin="c2a4.begin" repeatCount="indefinite">
    <mpath xlink:href="#motionPath" />
  </animateMotion>

Além das ids definidas, houve alteração em todos os atributos “begin”, além da adição do atributo “begin” em “c2a1”, aonde colocamos o valor “c1a1.begin + 1s” na linha destacada, referenciando o começo da animação do primeiro círculo, e começando a animação 1 segundo após isso.

Depois que você fizer tudo isso, haverá um atraso de 1 segundo para cada círculo. Então no sexto círculo, a animação começará em 5 segundos depois. E ficará tudo automatizado pelos atributos “begin”.

Agora as animações estão quase prontas. Só falta um detalhe: a transição de cores.

5. Criando a transição de cores

Ok, minha ideia aqui é o seguinte: vamos fazer cores animadas que homenageiam os dois esquemas de cores usados em trabalhos por web designers e designers gráficos: o RGB e o CMYK. Partiu!

Depois dos círculos, adicione essas duas linhas:

<animate xlink:href="#c1r" id="fill1" attributeName="fill" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="c1a4.begin" />
<animate xlink:href="#c1r" id="stroke1" attributeName="stroke" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="c1a4.begin" />

Primeiramente, perceba que são duas tags <animate> independentes e que sabem o que querem, ou seja, não estão dentro de nenhuma tag de forma. Mas essas duas tags não são tão independentes assim, porque elas precisam de um apoio para ir em frente. Então perceba que existe um atributo xlink:href apontando para o círculo com id “c1r”, que é um dos círculos que ficam seguindo o caminho “motionPath”.

Para cada linha, foi dado um id que aponta o que ela vai mexer, seguido de um número, somente para nos guiarmos. A primeira linha irá animar o preenchimento, então demos o id “fill1” para ela. A segunda animará o contorno, então demos o id “stroke1” para ela.

Logo, não é novidade o valor do atributo seguinte usado nas duas linhas, “attributeName” com o valor “fill” na primeira linha, e “stroke” na segunda. Agora, para esses dois atributos, precisamos definir como vai ser a animação deles.

Para isso, vamos usar o atributo “values” e colocar todas as cores que queremos. Com odito antes, vamos homenagear o RGB e o CMYK. Já sabemos que a cor padrão do SVG é preto, então o loop precisa começar e terminar com preto. A partir daí, vamos criar a fila de cores: vermelho – verde – azul – ciano – magenta – amarelo. O legal do HTML/CSS é que eles já reconhecem o nome de algumas cores, e no caso, RGB e CMYK não podiam ficar de fora.

Como inglês é o idioma oficial de qualquer linguagem de programação, temos que escrever as cores em inglês, e temos que separá-las usando “;”, ficando então assim: “black;red;green;blue;cyan;magenta;yellow;black”. Se preferir, você pode usar valores hexadecimais. Se quiser saber outros nomes de cores pré-definidas, clique aqui.

Depois definimos uma duração de 60 segundos (dur="60s"), repetição infinita (repeatCount="indefinite"), e que começa assim que o círculo “c1r” começa a seguir o “motionPath” (begin="c1a4.begin").

Agora deve ser aplicado a mesma animação para os outros 5 círculos, ficando assim:

<animate xlink:href="#c1r" id="fill1" attributeName="fill" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="c1a4.begin" />
<animate xlink:href="#c1r" id="stroke1" attributeName="stroke" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="c1a4.begin" />
<animate xlink:href="#c2r" id="fill2" attributeName="fill" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="fill1.begin + 1s" />
<animate xlink:href="#c2r" id="stroke2" attributeName="stroke" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="stroke1.begin + 1s" />
<animate xlink:href="#c3r" id="fill3" attributeName="fill" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="fill2.begin + 1s" />
<animate xlink:href="#c3r" id="stroke3" attributeName="stroke" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="stroke2.begin + 1s" />
<animate xlink:href="#c4r" id="fill4" attributeName="fill" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="fill3.begin + 1s" />
<animate xlink:href="#c4r" id="stroke4" attributeName="stroke" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="stroke3.begin + 1s" />
<animate xlink:href="#c5r" id="fill5" attributeName="fill" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="fill4.begin + 1s" />
<animate xlink:href="#c5r" id="stroke5" attributeName="stroke" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="stroke4.begin + 1s" />
<animate xlink:href="#c6r" id="fill6" attributeName="fill" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="fill5.begin + 1s" />
<animate xlink:href="#c6r" id="stroke6" attributeName="stroke" values="black;red;green;blue;cyan;magenta;yellow;black" dur="60s" repeatCount="indefinite" begin="stroke5.begin + 1s" />

Para facilitar nossas vidas, a partir do segundo círculo, o “begin” para o “fill2” muda para “fill1.begin + 1s”, indicando que tem que começar a animar o preenchimento 1 segundo depois do “fill1”. O mesmo acontece no “begin” do “stroke2”, mudando o “begin” para “stroke1.begin + 1s” para que ele anime o contorno 1 segundo depois do “stroke1”.

E assim vai sucessivamente até a animação de “stroke” e “fill” do sexto círculo.

6. Finalizado

E terminamos! Nossa animação de preloader ficou assim:

Espero que isso ajude-o a dar os passos para animações mais elaboradas! Até a próxima!

Manda sua palavra ae! Deixe um comentário: