Quarta das doze animações.
Animações de Carregamento (série de 13 partes)
Animação
Resultado final:
Introdução
Criei essa animação com SVG, seguindo uma estrutura parecida com as anteriores:
<!-- definições de tamanho --><svg> <defs> <!-- caminhos que os círculos percorrem --> <path /> <path /> <path /> <path /> <path /> </defs> <!-- plano de fundo --> <rect /> <!-- desenhos dos caminhos que os círculos percorrem, para debug --> <g> <use /> <use /> <use /> <use /> <use /> </g> <!-- quatro círculos como este --> <ellipse> <!-- animações que fazem o círculo percorrer os caminhos --> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <!-- animação que estica o círculo horizontalmente --> <animate /> <!-- animação que estica o círculo verticalmente --> <animate /> </ellipse></svg>Como funciona
Omiti alguns elementos e atributos nos blocos a seguir para manter a explicação concisa.
Tamanho
Mantive o tamanho igual às animações anteriores.
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
O caminho percorrido tem a forma de um pentágono, por onde quatro círculos se movimentam. Sempre que um vértice fica vazio, um dos círculos empurra outro em direção a esse vértice. Os movimentos seguem no sentido horário.
Primeiro, calculei a posição de cada vértice usando JavaScript.
Resultado
Código
// dimensõesconst width = 200;const height = 200;const xCenter = width / 2;const yCenter = height / 2;// pentágonoconst numberOfSides = 5;// vérticesconst radius = 35;const points = [];for (let i = 0; i < numberOfSides; i++) { const angle = ((2 * Math.PI) / numberOfSides) * i; const x = radius * Math.cos(angle) + xCenter; const y = radius * Math.sin(angle) + yCenter; points.push({ x, y });}/*[ { x: 135, y: 100 } { x: 110.81559480312316, y: 133.28697807033038 } { x: 71.68440519687684, y: 120.57248383023656 } { x: 71.68440519687684, y: 79.42751616976344 } { x: 110.81559480312315, y: 66.71302192966962 }]*/Em seguida, calculei os lados. Eles se estendem além dos vértices, criando espaço para que os círculos se movimentem, como se estivessem tomando impulso ou recebendo um empurrão.
Resultado
Código
// dimensõesconst width = 200;const height = 200;const xCenter = width / 2;const yCenter = height / 2;// pentágonoconst numberOfSides = 5;// vérticesconst radius = 35;const points = [];for (let i = 0; i < numberOfSides; i++) { const angle = ((2 * Math.PI) / numberOfSides) * i; const x = radius * Math.cos(angle) + xCenter; const y = radius * Math.sin(angle) + yCenter; points.push({ x, y });}/*[ { x: 135, y: 100 } { x: 110.81559480312316, y: 133.28697807033038 } { x: 71.68440519687684, y: 120.57248383023656 } { x: 71.68440519687684, y: 79.42751616976344 } { x: 110.81559480312315, y: 66.71302192966962 }]*/// ladosconst extension = 0.3;const edges = [];for (let i = 0; i < numberOfSides; i++) { const point1 = points[i]; const point2 = points[i + 1] || points[0]; const dx = point2.x - point1.x; const dy = point2.y - point1.y; const length = Math.hypot(dx, dy); const unitDx = dx / length; const unitDy = dy / length; const edgeExtension = length * extension; const x1 = point1.x - unitDx * edgeExtension; const y1 = point1.y - unitDy * edgeExtension; const x2 = point2.x + unitDx * edgeExtension; const y2 = point2.y + unitDy * edgeExtension; edges.push({ x1, y1, x2, y2 });}/*[ { x1: 142.25532155906305, y1: 90.01390657890089, x2: 103.56027324406011, y2: 143.2730714914295 }, { x1: 122.55495168499706, y1: 137.10132634235853, x2: 59.94504831500294, y2: 116.75813555820842 }, { x1: 71.68440519687684, y1: 132.9159741283785, x2: 71.68440519687684, y2: 67.08402587162149 }, { x1: 59.94504831500295, y1: 83.24186444179158, x2: 122.55495168499704, y2: 62.89867365764148 }, { x1: 103.5602732440601, y1: 56.72692850857051, x2: 142.25532155906305, y2: 109.98609342109911 }]*/// posição de cada vérticeconst extensionProportion = extension / (1 + 2 * extension);const leftVertice = 0 + extensionProportion; // 0.18749999999999997const rightVertice = 1 - extensionProportion; // 0.8125Com os lados calculados, defini dentro de defs os paths que os círculos percorrem. Eles serão referenciados pelos seus ids, motion-path-0 a motion-path-4.
Depois do rect, que é o plano de fundo, defini cinco uses para visualizar os caminhos, visto que o que é definido dentro de defs não é renderizado. Os elementos use são removidos na conclusão da animação.
Resultado
Código
<svg> <defs> <path id="motion-path-0" d="M142.25532155906305,90.01390657890089 L103.56027324406011,143.2730714914295" /> <path id="motion-path-1" d="M122.55495168499706,137.10132634235853 L59.94504831500294,116.75813555820842" /> <path id="motion-path-2" d="M71.68440519687684,132.9159741283785 L71.68440519687684,67.08402587162149" /> <path id="motion-path-3" d="M59.94504831500295,83.24186444179158 L122.55495168499704,62.89867365764148" /> <path id="motion-path-4" d="M103.5602732440601,56.72692850857051 L142.25532155906305,109.98609342109911" /> </defs> <rect /> <g fill="none" stroke="lightgray"> <use href="#motion-path-0" /> <use href="#motion-path-1" /> <use href="#motion-path-2" /> <use href="#motion-path-3" /> <use href="#motion-path-4" /> </g></svg>Círculos e suas animações
A duração final da animação é de oito segundos. Nesta seção as animações têm duração de 40 segundos para ficarem mais evidentes.
Animações que percorrem o caminho
Inicialmente, criei as animações do círculo que empurra e do círculo que é empurrado. A ideia era reutilizar essas animações nos outros dois círculos, alterando apenas o tempo de início.
Animando o círculo que empurra
Começando com o círculo que empurra, usei um elemento ellipse, pois ele permite definir o raio nos eixos x e y separadamente.
Defini cinco elementos animateMotion, cada um contendo um elemento mpath que referencia os paths de #motion-path-0 a #motion-path-4. Cada animateMotion possui os seguintes atributos:
id: vai decircle_1_path_0acircle_1_path_4begin: cada animação começa quando a anterior termina, repetindo indefinidamente#circle_1_path_0,0ms; circle_1_path_4.end:0msfaz com que esta seja a primeira animação a executar, ecircle_1_path_4.endfaz com que animação seja executada quandocircle_1_path_4termina#circle_1_path_1a#circle_1_path_4: começam suas animações quando a animação anterior termina
Os seguinte atributos são iguais para todos os animateMotions:
dur="8000ms": a animação dura 40 segundos nos exemplos, cadaanimateMotiondura 1/5 da duração total, que são oito segundoscalcMode="spline": para poder usar curvas de Bézier no atributokeySplinesrotate="auto": para que o círculo siga a rotação do caminhokeyTimes,keyPointsekeySplines: dado que funcionam juntos, representei os valores dos atributos em uma tabela:
keyTimes | keyPoints | keySplines |
|---|---|---|
| 0 | 0.18749999999999997 (vértice esquerdo) | 0.25, 0.75, 1, 1 |
| 0.2 | 0 | 0.42, 0, 0.58, 1 |
| 0.3 | 1 | 0.42, 0, 0.58, 1 |
| 0.5 | 0.8125 (vértice direito) | 0, 0, 1, 1 |
| 1 | 0.8125 (vértice direito) | - |
Lembrando como funcionam:
keyTimes: define em quais momentos específicos ao longo da animação oskeyPointsocorrerão, varia de0a1keyPoints: define onde o círculo deve estar ao longo do caminho, varia de0a1keySplines: define curvas de Bézier para suavizar a progressão entrekeyPoints
Representação em gráfico:
- Os eixos
xeyrepresentam os valores dos atributoskeyTimesekeyPoints, respectivamente - No topo e à direita, as linhas em cinza escuro representam os intervalos onde os valores do atributo
keySplinessão aplicados
Ou seja, na primeira metade da animação, o círculo começa no vértice esquerdo, pega impulso e se move rapidamente para a outra extremidade da linha, parando no vértice direito. Dessa forma, a animação seguinte se inicia na mesma posição, mantendo a animação contínua.
Na segunda metade o círculo fica parado, é nesse intervalo que o outro par de círculos é animado.
Apenas o círculo que empurra animado
Código
<svg> <defs> <path /> <path /> <path /> <path /> <path /> </defs> <rect /> <g> <use /> <use /> <use /> <use /> <use /> </g> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_1_path_0" dur="8000ms" calcMode="spline" begin="0ms; circle_1_path_4.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> <animateMotion id="circle_1_path_1" dur="8000ms" calcMode="spline" begin="circle_1_path_0.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animateMotion id="circle_1_path_2" dur="8000ms" calcMode="spline" begin="circle_1_path_1.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animateMotion id="circle_1_path_3" dur="8000ms" calcMode="spline" begin="circle_1_path_2.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_1_path_4" dur="8000ms" calcMode="spline" begin="circle_1_path_3.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> </ellipse></svg>Animando o círculo que é empurrado
Assim como com o círculo que empurra, usei um elemento ellipse contendo cinco elementos animateMotion. Cada animateMotion contém um elemento mpath, que desta vez começa referenciando o path#motion-path-1, um path à frente da animação do círculo que empurra.
Cada animateMotion possui os seguintes atributos:
idebegin: assim como no círculo que empurra, porém comcircle_2_em vez decircle_1_dur,calcMode,rotate: iguais ao círculo que empurrakeyTimes,keyPointsekeySplines:
keyTimes | keyPoints | keySplines |
|---|---|---|
| 0 | 0.18749999999999997 (vértice esquerdo) | 0, 0, 1, 1 |
| 0.26 | 0.18749999999999997 (vértice esquerdo) | 0.25, 0.75, 1, 1 |
| 0.36 | 1 | 0.42, 0, 0.58, 1 |
| 0.5 | 0.8125 (vértice direito) | 0.42, 0, 0.58, 1 |
| 1 | 0.8125 (vértice direito) | - |
Representação em gráfico:
Ou seja, na primeira metade da animação, o círculo começa no vértice esquerdo, leva o empurrão e se move rapidamente para a outra extremidade da linha, parando no vértice direito. Dessa forma, a animação seguinte se inicia na mesma posição, mantendo a animação contínua.
Na segunda metade o círculo fica parado, é nesse intervalo que o outro par de círculos é animado.
Primeiro par de círculos animado
Código
<svg> <defs> <path /> <path /> <path /> <path /> <path /> </defs> <rect /> <g> <use /> <use /> <use /> <use /> <use /> </g> <ellipse> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> </ellipse> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_2_path_0" dur="8000ms" calcMode="spline" begin="0ms; circle_2_path_4.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animateMotion id="circle_2_path_1" dur="8000ms" calcMode="spline" begin="circle_2_path_0.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animateMotion id="circle_2_path_2" dur="8000ms" calcMode="spline" begin="circle_2_path_1.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_2_path_3" dur="8000ms" calcMode="spline" begin="circle_2_path_2.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> <animateMotion id="circle_2_path_4" dur="8000ms" calcMode="spline" begin="circle_2_path_3.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> </ellipse></svg>Animações que esticam
Em seguida, fiz as animações que distorcem os círculos de alguma forma.
Animando rx e ry do círculo que empurra
Para transmitir a ideia de impulso e velocidade, criei duas animações que, em conjunto, esticam os círculos horizontal e verticalmente.
Os elementos animate possuem atributos com o mesmo valor:
repeatCount="indefinite": a animação repete indefinidamentedur="8000ms": a duração é de oito segundos para os exemploskeyTimes="0; 0.2; 0.3; 0.5; 1": define em quais momentos específicos ao longo da animação osvaluesserão assumidos pelo atributoattributeName, varia de0a1
Para o atributo values:
attributeName="rx" | attributeName="ry" | Descrição |
|---|---|---|
| 8 | 8 | Começa redondo |
| 7.6 | 8.4 | Estica verticalmente e encolhe horizontalmente ao pegar impulso |
| 8.4 | 7.6 | Estica horizontalmente e encolhe verticalmente ao empurrar |
| 8 | 8 | Volta a ser redondo |
| 8 | 8 | Se mantém redondo |
Apenas o círculo que empurra animado
Código
<svg> <defs> <path /> <path /> <path /> <path /> <path /> </defs> <rect /> <g> <use /> <use /> <use /> <use /> <use /> </g> <ellipse> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="8000ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 7.6; 8.4; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="8000ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 8.4; 7.6; 8; 8" /> </ellipse> <ellipse> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> </ellipse></svg>Animando rx e ry do círculo que é empurrado
Para transmitir a ideia de impacto e velocidade, criei duas animações que, em conjunto, esticam os círculos horizontal e verticalmente.
Os elementos animate possuem atributos com o mesmo valor:
repeatCount="indefinite": a animação repete indefinidamentedur="8000ms": a duração é de oito segundos para os exemploskeyTimes="0; 0.26; 0.36; 0.5; 1": define em quais momentos específicos ao longo da animação osvaluesserão assumidos pelo atributoattributeName, varia de0a1
Para o atributo values:
attributeName="rx" | attributeName="ry" | Descrição |
|---|---|---|
| 8 | 8 | Começa redondo |
| 8 | 8 | Se mantém redondo |
| 7.6 | 8.4 | Estica verticalmente e encolhe horizontalmente no impacto |
| 8 | 8 | Volta a ser redondo |
| 8 | 8 | Se mantém redondo |
Primeiro par de círculos animado
Código
<svg> <defs> <path /> <path /> <path /> <path /> <path /> </defs> <rect /> <g> <use /> <use /> <use /> <use /> <use /> </g> <ellipse> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animate /> <animate /> </ellipse> <ellipse> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="8000ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 7.6; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="8000ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 8.4; 8; 8" /> </ellipse></svg>Animando o segundo par de círculos
O segundo par de círculos é basicamente igual ao primeiro, o que muda são:
ids de cadaanimateMotion: é como nos outros círculos, mas começando comcircle_3_ecircle_4_begins das animações de cadaellipse: animações começam com antecedência de metade do tempo da animação,-4000msnos exemplospaths de cadampath: o terceiro círculo começa empath#motion-path-2, e o quarto empath#motion-path-3
Todos os círculos animados
Código
<svg> <defs> <path /> <path /> <path /> <path /> <path /> </defs> <rect /> <g> <use /> <use /> <use /> <use /> <use /> </g> <ellipse> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animate /> <animate /> </ellipse> <ellipse> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animateMotion> <mpath /> </animateMotion> <animate /> <animate /> </ellipse> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_3_path_0" dur="8000ms" calcMode="spline" begin="-4000ms; circle_3_path_4.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animateMotion id="circle_3_path_1" dur="8000ms" calcMode="spline" begin="circle_3_path_0.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_3_path_2" dur="8000ms" calcMode="spline" begin="circle_3_path_1.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> <animateMotion id="circle_3_path_3" dur="8000ms" calcMode="spline" begin="circle_3_path_2.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> <animateMotion id="circle_3_path_4" dur="8000ms" calcMode="spline" begin="circle_3_path_3.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="8000ms" begin="-4000ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 7.6; 8.4; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="8000ms" begin="-4000ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 8.4; 7.6; 8; 8" /> </ellipse> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_4_path_0" dur="8000ms" calcMode="spline" begin="-4000ms; circle_4_path_4.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_4_path_1" dur="8000ms" calcMode="spline" begin="circle_4_path_0.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> <animateMotion id="circle_4_path_2" dur="8000ms" calcMode="spline" begin="circle_4_path_1.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> <animateMotion id="circle_4_path_3" dur="8000ms" calcMode="spline" begin="circle_4_path_2.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animateMotion id="circle_4_path_4" dur="8000ms" calcMode="spline" begin="circle_4_path_3.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="8000ms" begin="-4000ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 7.6; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="8000ms" begin="-4000ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 8.4; 8; 8" /> </ellipse></svg>Conclusão
Como na animação anterior, usei o JavaScript para calcular os valores de vários atributos, e também usei os gráficos que ilustram como os atributos keyTimes, keyPoints e keySplines funcionam em conjunto. Isso tudo facilitou a experimentação ao longo do desenvolvimento da animação.
Além de aplicar tudo o que aprendi ao longo das animações anteriores, usei pela primeira vez um syncbase value no atributo begin. Isso facilitou bastante o gerenciamento de vários elementos animateMotion usados em conjunto em um mesmo elemento ellipse. É uma ferramenta que planejo usar nas próximas animações.
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-0" d="M142.25532155906305,90.01390657890089 L103.56027324406011,143.2730714914295" /> <path id="motion-path-1" d="M122.55495168499706,137.10132634235853 L59.94504831500294,116.75813555820842" /> <path id="motion-path-2" d="M71.68440519687684,132.9159741283785 L71.68440519687684,67.08402587162149" /> <path id="motion-path-3" d="M59.94504831500295,83.24186444179158 L122.55495168499704,62.89867365764148" /> <path id="motion-path-4" d="M103.5602732440601,56.72692850857051 L142.25532155906305,109.98609342109911" /> </defs> <rect width="199" height="199" x="0.5" y="0.5" fill="white" stroke="lightgray" stroke-width="1" rx="6" /> <!-- início: círculo 1 --> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_1_path_0" dur="1600ms" calcMode="spline" begin="0ms; circle_1_path_4.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> <animateMotion id="circle_1_path_1" dur="1600ms" calcMode="spline" begin="circle_1_path_0.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animateMotion id="circle_1_path_2" dur="1600ms" calcMode="spline" begin="circle_1_path_1.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animateMotion id="circle_1_path_3" dur="1600ms" calcMode="spline" begin="circle_1_path_2.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_1_path_4" dur="1600ms" calcMode="spline" begin="circle_1_path_3.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="1600ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 7.6; 8.4; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="1600ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 8.4; 7.6; 8; 8" /> </ellipse> <!-- fim: círculo 1 --> <!-- início: círculo 2 --> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_2_path_0" dur="1600ms" calcMode="spline" begin="0ms; circle_2_path_4.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animateMotion id="circle_2_path_1" dur="1600ms" calcMode="spline" begin="circle_2_path_0.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animateMotion id="circle_2_path_2" dur="1600ms" calcMode="spline" begin="circle_2_path_1.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_2_path_3" dur="1600ms" calcMode="spline" begin="circle_2_path_2.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> <animateMotion id="circle_2_path_4" dur="1600ms" calcMode="spline" begin="circle_2_path_3.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="1600ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 7.6; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="1600ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 8.4; 8; 8" /> </ellipse> <!-- fim: círculo 2 --> <!-- início: círculo 3 --> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_3_path_0" dur="1600ms" calcMode="spline" begin="-800ms; circle_3_path_4.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animateMotion id="circle_3_path_1" dur="1600ms" calcMode="spline" begin="circle_3_path_0.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_3_path_2" dur="1600ms" calcMode="spline" begin="circle_3_path_1.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> <animateMotion id="circle_3_path_3" dur="1600ms" calcMode="spline" begin="circle_3_path_2.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> <animateMotion id="circle_3_path_4" dur="1600ms" calcMode="spline" begin="circle_3_path_3.end" keyTimes="0; 0.2; 0.3; 0.5; 1" keyPoints="0.18749999999999997; 0; 1; 0.8125; 0.8125" keySplines="0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="1600ms" begin="-800ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 7.6; 8.4; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="1600ms" begin="-800ms" keyTimes="0; 0.2; 0.3; 0.5; 1" values="8; 8.4; 7.6; 8; 8" /> </ellipse> <!-- fim: círculo 3 --> <!-- início: círculo 4 --> <ellipse rx="8" ry="8" fill="black"> <animateMotion id="circle_4_path_0" dur="1600ms" calcMode="spline" begin="-800ms; circle_4_path_4.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-3" /> </animateMotion> <animateMotion id="circle_4_path_1" dur="1600ms" calcMode="spline" begin="circle_4_path_0.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-4" /> </animateMotion> <animateMotion id="circle_4_path_2" dur="1600ms" calcMode="spline" begin="circle_4_path_1.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-0" /> </animateMotion> <animateMotion id="circle_4_path_3" dur="1600ms" calcMode="spline" begin="circle_4_path_2.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-1" /> </animateMotion> <animateMotion id="circle_4_path_4" dur="1600ms" calcMode="spline" begin="circle_4_path_3.end" keyTimes="0; 0.26; 0.36; 0.5; 1" keyPoints="0.18749999999999997; 0.18749999999999997; 1; 0.8125; 0.8125" keySplines="0, 0, 1, 1; 0.25, 0.75, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1" rotate="auto" > <mpath href="#motion-path-2" /> </animateMotion> <animate attributeName="rx" repeatCount="indefinite" dur="1600ms" begin="-800ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 7.6; 8; 8" /> <animate attributeName="ry" repeatCount="indefinite" dur="1600ms" begin="-800ms" keyTimes="0; 0.26; 0.36; 0.5; 1" values="8; 8; 8.4; 8; 8" /> </ellipse> <!-- fim: círculo 4 --></svg>