Primeira das doze animações.
Animações de Carregamento (série de 10 partes)
Animação
Resultado final:
Introdução
Criei essa animação com SVG, seguindo essa estrutura:
<!-- definições de tamanho --><svg> <defs> <!-- caminho que o círculo percorre --> <path /> </defs> <!-- plano de fundo --> <rect /> <!-- desenho do caminho que o círculo percorre, para debug --> <path /> <!-- círculo --> <ellipse> <!-- animação que faz o círculo percorrer o caminho --> <animateMotion> <mpath /> </animateMotion> <!-- animação que estica o círculo horizontalmente --> <animate /> <!-- animação que estica o círculo verticalmente --> <animate /> <!-- animação que rotaciona o círculo --> <animateTransform /> </ellipse></svg>Como funciona
Omiti alguns elementos e atributos nos blocos a seguir para manter a explicação concisa.
Tamanho
Aqui defini que a animação tem 200 pixels de largura e altura no elemento svg.
Com um elemento rect, defini o plano de fundo branco com borda cinza e cantos arredondados. O stroke é desenhado centralizado na borda do rect, ou seja, metade dentro e metade fora. Como defini strokeWidth de 1 pixel, para que metade do stroke não ficasse cortada, subtraí 1 pixel de width (0,5 pixels da esquerda e da direita) e height (0,5 pixels de cima e de baixo) e movi 0,5 pixels nos eixos x e y. Dessa forma, a borda não é cortada pelos limites de altura e largura definidos no elemento svg.
Resultado
Código
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200"> <rect width="199" height="199" x="0.5" y="0.5" fill="white" stroke="lightgray" strokeWidth="1" rx="6" /></svg>Caminho
Dentro de defs, defini o path que será o caminho que o círculo percorre. Ele será referenciado pelo seu id, motion-path. O caminho é uma curva quadrática definida usando o comando Q.
Depois do rect, que é o plano de fundo, defini outro path para visualizar o caminho, visto que o que é definido dentro de defs não é renderizado. Esse path é removido na conclusão da animação.
Resultado
Código
<svg> <defs> <path id="motion-path" d="M50,150 Q100,0 150,150" /> </defs> <rect></rect> <path d="M50,150 Q100,0 150,150" fill="none" stroke="lightgray" strokeWidth="1" /></svg>Círculo e suas animações
A duração final da animação é de um segundo e meio. Nesta seção as animações têm duração de 10 segundos para ficarem mais evidentes.
Animação que percorre o caminho
Inicialmente, criei a animação que define o ciclo de ida e volta do círculo.
Defini o círculo com um elemento ellipse, pois ele permite definir o raio nos eixos x e y separadamente. Usei os raios diferentes para deformar o círculo durante a animação. O elemento mpath referencia o path#motion-path, enquanto o elemento animateMotion define a animação.
No elemento animateMotion, defini os atributos da seguinte forma:
repeatCount="indefinite": a animação repete indefinidamente.dur="10000ms": a duração é de 10 segundos para os exemplos.calcMode="spline": para poder usar curvas de Bézier no atributokeySplines.keyTimes: Define em quais momentos específicos durante a duração da animação oskeyPointsocorrerão, varia de0a1. Nesse caso, defini três momentos:0, que é o início;0.5; que é o meio;1, que é o fim.keyPoints: Define onde o círculo deve estar ao longo do caminho, varia de0a1. Defini três posições para cada momento dokeyTimes:0, que é o início do caminho,1que é o final do caminho;0, que volta ao início do caminho. Ou seja, no primeiro momento a posição é o início do caminho, no segundo é o final, e no terceiro é o início novamente, completando o ciclo de animação.keySplines: Define curvas de Bézier para suavizar a progressão entrekeyPoints. Defini a mesma curva na ida e na volta:x1 = 0.2,y1 = 0.6,x2 = 0.7ey2 = 0.4(visualização em cubic-bezier.com). É uma curva ligeiramente mais rápida no início, mais lenta no meio, e que acelera novamento no final. Dessa forma, o círculo se move rapidamente nos pontos de impacto, enquanto se move mais lentamente quando está no ar.
Resultado
Código
<svg> <defs></defs> <rect /> <path /> <ellipse rx="8" ry="8" fill="black"> <animateMotion repeatCount="indefinite" dur="10000ms" calcMode="spline" keyTimes="0; 0.5; 1" keyPoints="0; 1; 0" keySplines="0.2,0.6,0.7,0.4; 0.2,0.6,0.7,0.4" > <mpath href="#motion-path" /> </animateMotion> </ellipse></svg>Animações que esticam
Em seguida, fiz as animações que distorcem o círculo de alguma forma.
Animando rx
Para transmitir a ideia de impacto, criei uma animação que estica o círculo horizontalmente quando ele atinge o chão.
No elemento animate, defini os atributos da seguinte forma:
attributeName="rx": representa o raio no eixox.repeatCount="indefinite": a animação repete indefinidamente.dur="10000ms": a duração é de 10 segundos para os exemplos.calcMode="spline": para poder usar curvas de Bézier no atributokeySplines.keyTimes: Define em quais momentos específicos durante a duração da animação osvaluesserão assumidos pelo atributoattributeName, varia de0a1. Nesse caso, defini cinco momentos:0, que é o início do arco;0.25, que é o topo do arco;0.5, que é o fim do arco;0.75, que é o topo do arco novamente;1, que é o início do arco novamente.values: Define os valores que o atributoattributeNameassumirá. Defini cinco valores para cada momento dokeyTimes:10no início do arco;8no topo do arco;10no fim do arco;8no topo do arco novamente;10no início do arco novamente. Ou seja, o raio aumenta para10no início e fim do arco, e volta para8nos outros momentos.keySplines: Define curvas de Bézier para suavizar a progressão entrevalues. Defini as mesmas duas curvas na ida e na volta:x1 = 0,y1 = 1,x2 = 1ey2 = 1(visualização em cubic-bezier.com). É uma curva veloz no início e que desacelera na metade para o final. Dessa forma, o valor vai de10a8de forma rápida na primeira metade da curva.x1 = 1,y1 = 0,x2 = 1ey2 = 0(visualização em cubic-bezier.com). É uma curva vagarosa no início e que acelera bastante no final. Dessa forma, o valor vai de8a10de forma rápida apenas no fim da curva.- Dessa forma, o círculo se deforma rapidamente nos pontos de impacto, enquanto volta ao normal quando está no ar.
Apenas rx animado
Animando ry
Para transmitir a ideia de velocidade, criei uma animação que estica o círculo verticalmente quando ele está em movimento no ar. Porém, essa animação não leva em conta a trajetório do círculo, isso é resolvido na próxima seção.
No elemento animate, defini os atributos da seguinte forma:
attributeName="ry": representa o raio no eixoy.repeatCount="indefinite": a animação repete indefinidamente.dur="10000ms": a duração é de 10 segundos para os exemplos.calcMode="spline": para poder usar curvas de Bézier no atributokeySplines.keyTimes: Define em quais momentos específicos durante a duração da animação osvaluesserão assumidos pelo atributoattributeName, varia de0a1. Nesse caso, defini cinco momentos:0, que é o início do arco;0.25, que é o topo do arco;0.5, que é fim do arco;0.75, que é o topo do arco novamente;1, que é o início do arco novamente.values: Define os valores que o atributoattributeNameassumirá. Defini cinco valores para cada da momento dokeyTimes:8no início do arco;8.6no topo do arco;8no fim do arco;8.6no topo do arco novamente;8no início do arco novamente. Ou seja, o raio aumenta para8.6enquanto o círculo está no topo do arco, e volta para8nos outros momentos.keySplines: Define curvas de Bézier para suavizar a progressão entrevalues. Defini as mesmas duas curvas na ida e na volta:x1 = 0,y1 = 1,x2 = 0.5ey2 = 1(visualização em cubic-bezier.com). É uma curva veloz no início e que desacelera mais para o final. Dessa forma, o valor vai de8a8.6de forma rápida.x1 = 1,y1 = 0,x2 = 1ey2 = 0(visualização em cubic-bezier.com). É uma curva vagarosa no início e que acelera bastante no final. Dessa forma, o valor vai de8.6a8de forma rápida apenas no fim da curva.- Dessa forma, o círculo se deforma ligeiramente enquanto está no ar.
Apenas ry animado
Resultado
Código
<svg> <defs></defs> <rect /> <path /> <ellipse> <animateMotion></animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="10000ms" calcMode="spline" values="10; 8; 10; 8; 10" keyTimes="0; 0.25; 0.5; 0.75; 1" keySplines="0,1,1,1; 1,0,1,0; 0,1,1,1; 1,0,1,0" /> <animate attributeName="ry" repeatCount="indefinite" dur="10000ms" calcMode="spline" values="8; 8.6; 8; 8.6; 8" keyTimes="0; 0.25; 0.5; 0.75; 1" keySplines="0,1,0.5,1; 1,0,1,0; 0,1,0.5,1; 1,0,1,0" /> </ellipse></svg>Animação que rotaciona
Em seguida, fiz a animação que rotaciona o círculo para que a animação do atributo ry siga a trajetória correta.
No elemento animateTransform, defini os atributos da seguinte forma:
attributeName="transform": atributo de transformação.repeatCount="indefinite": a animação repete indefinidamente.dur="10000ms": a duração é de 10 segundos para os exemplos.type="rotate": tipo rotação.keyTimes: Define em quais momentos específicos durante a duração da animação osvaluesserão assumidos pelo atributeattributeName, varia de0a1. Nesse caso, defini três momentos:0, que é o início;0.5, que é o meio;1, que é o fim.values: Define os valores que o atributoattributeNameassumirá. Defini três valores para cada da momento dokeyTimes:0, sem rotação;180, meia volta;0, sem rotação novamente. Ou seja, no intervalo em que o círculo se movimenta entre um extremo e outro do arco, o círculo completa meia volta.- Não é necessário definir
calcModeekeySplines, visto que a animação é linear.
Resultado
Código
<svg> <defs></defs> <rect /> <path /> <ellipse> <animateMotion></animateMotion> <animate /> <animate /> <animateTransform attributeName="transform" repeatCount="indefinite" dur="10000ms" type="rotate" values="0; 180; 0" keyTimes="0; 0.5; 1" /> </ellipse></svg>Conclusão
Foi uma animação divertida de criar, pois me permitiu explorar novas técnicas com SVG. Ainda não tinha tido a oportunidade de usar os elementos animateMotion, animateTransform e mpath, que são fundamentais para criar movimentos mais fluidos e dinâmicos. O elemento animateMotion, por exemplo, foi essencial para fazer com que o círculo seguisse uma trajetória de maneira simples.
Durante o processo, aprendi mais sobre o funcionamento das curvas de Bézier no atributo keySplines, o que me proporcionou um controle mais preciso sobre a aceleração e desaceleração das animações, permitindo criar transições mais naturais. Um dos desafios foi ajustar esses valores para obter um movimento orgânico, e a experimentação com diferentes curvas foi essencial para alcançar a animação que eu tinha em mente.
Além disso, estudar essas técnicas ampliou minha compreensão do SVG como um todo, o que certamente será útil para as próximas postagens.
Resultado
Código
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200"> <defs> <path id="motion-path" d="M50,150 Q100,0 150,150" /> </defs> <rect width="199" height="199" x="0.5" y="0.5" fill="white" stroke="lightgray" strokeWidth="1" rx="6" /> <ellipse rx="8" ry="8" fill="black"> <animateMotion repeatCount="indefinite" dur="1500ms" calcMode="spline" keyTimes="0; 0.5; 1" keyPoints="0; 1; 0" keySplines="0.2,0.6,0.7,0.4; 0.2,0.6,0.7,0.4" > <mpath href="#motion-path" /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="1500ms" calcMode="spline" values="10; 8; 10; 8; 10" keyTimes="0; 0.25; 0.5; 0.75; 1" keySplines="0,1,1,1; 1,0,1,0; 0,1,1,1; 1,0,1,0" /> <animate attributeName="ry" repeatCount="indefinite" dur="1500ms" calcMode="spline" values="8; 8.6; 8; 8.6; 8" keyTimes="0; 0.25; 0.5; 0.75; 1" keySplines="0,1,0.5,1; 1,0,1,0; 0,1,0.5,1; 1,0,1,0" /> <animateTransform attributeName="transform" repeatCount="indefinite" dur="1500ms" type="rotate" values="0; 180; 0" keyTimes="0; 0.5; 1" /> </ellipse></svg>