Oitava das doze animações.
Animações de Carregamento (série de 13 partes)
Animação
A animação é composta por círculos que percorrem uma curva de Lissajous.
Introdução
Criei essa animação com SVG. A estrutura segue o padrão das anteriores:
<!-- definições de tamanho --><svg> <defs> <!-- caminho que os círculos percorrem --> <path /> </defs> <!-- plano de fundo --> <rect /> <!-- desenho do caminho que os círculos percorrem, para debug --> <use /> <!-- oito círculos como este --> <animateMotion> <mpath></mpath> </animateMotion></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" stroke-width="1" rx="6" /></svg>Caminho
Para criar o caminho, usei JavaScript para gerar a curva de Lissajous dinamicamente:
// dimensõesconst WIDTH = 200;const HEIGHT = 200;const X_CENTER = WIDTH * (1 / 2);const Y_CENTER = HEIGHT * (1 / 2);const X_MARGIN = 25; // distância entre a curva e as bordas horizontaisconst Y_MARGIN = 75; // distância entre a curva e as bordas verticaisconst X_RADIUS = (WIDTH - 2 * X_MARGIN) * (1 / 2);const Y_RADIUS = (HEIGHT - 2 * Y_MARGIN) * (1 / 2);// curvaconst TAU = 2 * Math.PI;const POINTS_AMOUNT = 100; // quanto mais pontos, mais suave é a curvaconst A_FREQUENCY = 1;const B_FREQUENCY = 3;const OFFSET = -1 * (1 / 2) * Math.PI; // deslocamento para que a curva comece à esquerdalet d = "";for (let i = 0; i < POINTS_AMOUNT; i++) { const pointIndex = i / POINTS_AMOUNT; const at = A_FREQUENCY * TAU * pointIndex + OFFSET; const bt = B_FREQUENCY * TAU * pointIndex + OFFSET; const x = X_CENTER + X_RADIUS * Math.sin(at); const y = Y_CENTER + Y_RADIUS * Math.cos(bt); if (i === 0) { d += `M${x},${y} `; continue; } d += `L${x},${y} `;}d += `z`;// M25,100 L25.14799536787963,104.68453286464312 ... L25.14799536787963,95.31546713535694 zResultado
Código
<svg> <def> <path id="path" d=" M25,100 L25.14799536787963,104.68453286464312 ... L25,99.99999999999994 z " /> </def> <rect /> <use href="#path" stroke="lightgray" fill="none" /></svg>Círculos e suas animações
Com o caminho pronto, o próximo passo foi criar os círculos e definir como eles se movimentariam sobre ele.
Animações que percorrem o caminho
A ideia é simples: cada círculo apenas segue o caminho que foi definido. Ao se moverem de um extremo ao outro, uma curva de Bézier ease-in-out é aplicada, ela começa mais lenta, acelera no meio, e desacelera no final.
Os elementos ellipse compartilham os seguintes atributos:
fill="black": cor de preenchimento da elipserx="8": raio horizontal da elipsery="8": raio vertical da elipse
Os elementos animateMotion compartilham os seguintes atributos:
dur="20000ms": duração total da animação, 20 segundosbegin="<atraso>": atraso antes do início da animação, cada círculo tem um atraso igualmente espaçadorepeatCount="indefinite": a animação se repete indefinidamentecalcMode="spline": usa uma curva de Bézier para a interpolaçãokeyPoints="0; 0.5; 1": pontos-chave da animaçãokeyTimes="0; 0.5; 1": tempos correspondentes aos pontos-chavekeySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6": curvas de Bézier para a interpolação
keyTimes | keyPoints | keySplines |
|---|---|---|
| 0 | 0 | 0.5, 0.4, 0.5, 0.6 |
| 0.5 | 0.5 | 0.5, 0.4, 0.5, 0.6 |
| 1 | 1 | - |
Os elementos mpath compartilham um atributo:
href="#path": referência ao caminho que a animação deve seguir
Resultado
Código
<svg> <def> <path /> </def> <rect /> <use /> <!-- começo: círculo 1 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-20000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 1 --> </ellipse> <!-- começo: círculo 2 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-17500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 2 --> </ellipse> <!-- começo: círculo 3 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-15000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 3 --> </ellipse> <!-- começo: círculo 4 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-12500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 4 --> </ellipse> <!-- começo: círculo 5 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-10000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 5 --> </ellipse> <!-- começo: círculo 6 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-7500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 6 --> </ellipse> <!-- começo: círculo 7 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-5000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 7 --> </ellipse> <!-- começo: círculo 8 --> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-2500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> <!-- fim: círculo 8 --> </ellipse></svg>Conclusão
A oitava animação foi uma experiência ótima. Trabalhar com curvas de Lissajous trouxe um visual único. Além disso, a aplicação da curva de Bézier na animação dos círculos foi essencial para garantir que eles não se sobrepusessem, permitindo que cada elemento tivesse seu próprio espaço visual. A utilização de JavaScript me deu a liberdade de experimentar de maneira dinâmica com o número de pontos na curva e seu posicionamento, possibilitando ajustes finos e testes em tempo real.
Resultado
Código
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200" height="200"> <def> <path id="path" d=" M25,100 L25.14799536787963,104.68453286464312 L25.591397401414156,109.20311381711696 L26.328456195348352,113.39566987447492 L27.356262915352673,117.11367764821722 L28.67076127786349,120.22542485937369 L30.266763558381143,122.62067631165048 L32.137971065048546,124.21457902821578 L34.27699899671023,124.9506682107068 L36.67540558734887,124.80286753286194 L39.32372542187894,123.77641290737884 L42.21150679181581,121.9076670010966 L45.32735294339413,119.26283106939474 L48.658967055348356,115.93559974371725 L52.19320076884828,112.04384185254288 L55.916106078064516,107.72542485937369 L59.81299037657526,103.1333308391076 L63.868474442371365,98.43023701176716 L68.06655313261956,93.78275282087864 L72.39065854864916,89.35551771087319 L76.82372542187895,85.30536869268818 L81.34825846263588,81.77578431446472 L85.94640140607065,78.89180186244963 L90.60000748267719,76.75558785279371 L95.29071103530148,75.44281873178278 L100,75 L104.70928896469852,75.44281873178278 L109.39999251732283,76.75558785279372 L114.05359859392937,78.89180186244963 L118.6517415373641,81.7757843144647 L123.17627457812105,85.30536869268818 L127.60934145135084,89.35551771087317 L131.93344686738047,93.78275282087864 L136.13152555762866,98.43023701176718 L140.18700962342476,103.1333308391076 L144.0838939219355,107.72542485937367 L147.80679923115173,112.04384185254287 L151.34103294465166,115.93559974371723 L154.67264705660585,119.26283106939474 L157.78849320818418,121.9076670010966 L160.67627457812105,123.77641290737884 L163.32459441265112,124.80286753286194 L165.72300100328977,124.9506682107068 L167.86202893495147,124.21457902821578 L169.73323644161886,122.6206763116505 L171.3292387221365,120.22542485937369 L172.64373708464734,117.1136776482172 L173.67154380465166,113.39566987447493 L174.40860259858584,109.20311381711694 L174.85200463212038,104.68453286464315 L175,100.00000000000001 L174.85200463212038,95.31546713535687 L174.40860259858584,90.79688618288307 L173.67154380465166,86.60433012552508 L172.64373708464734,82.88632235178277 L171.3292387221365,79.77457514062633 L169.73323644161883,77.3793236883495 L167.86202893495147,75.78542097178422 L165.72300100328977,75.0493317892932 L163.32459441265115,75.19713246713805 L160.67627457812105,76.22358709262116 L157.7884932081842,78.0923329989034 L154.67264705660585,80.73716893060526 L151.34103294465166,84.06440025628275 L147.80679923115173,87.95615814745713 L144.0838939219355,92.2745751406263 L140.18700962342473,96.8666691608924 L136.13152555762863,101.56976298823285 L131.9334468673804,106.21724717912137 L127.60934145135089,110.64448228912678 L123.17627457812107,114.69463130731182 L118.65174153736415,118.22421568553526 L114.05359859392934,121.10819813755037 L109.39999251732284,123.24441214720628 L104.70928896469849,124.55718126821722 L100.00000000000001,125 L95.29071103530153,124.55718126821722 L90.60000748267717,123.24441214720629 L85.94640140607068,121.10819813755037 L81.34825846263587,118.22421568553528 L76.82372542187895,114.69463130731184 L72.39065854864913,110.64448228912681 L68.06655313261962,106.21724717912139 L63.86847444237137,101.56976298823288 L59.81299037657529,96.86666916089243 L55.91610607806452,92.27457514062637 L52.1932007688483,87.95615814745712 L48.65896705534835,84.06440025628278 L45.32735294339415,80.7371689306053 L42.2115067918158,78.0923329989034 L39.32372542187895,76.22358709262116 L36.675405587348855,75.19713246713806 L34.27699899671023,75.0493317892932 L32.13797106504852,75.78542097178422 L30.26676355838117,77.37932368834947 L28.67076127786349,79.7745751406263 L27.356262915352673,82.88632235178282 L26.328456195348352,86.60433012552502 L25.59139740141417,90.79688618288304 L25.14799536787963,95.31546713535694 L25,99.99999999999994 z " /> </def> <rect width="199" height="199" x="0.5" y="0.5" fill="white" stroke="lightgray" stroke-width="1" rx="6" /> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-20000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-17500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-15000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-12500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-10000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-7500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-5000ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse> <ellipse fill="black" rx="8" ry="8"> <animateMotion dur="20000ms" begin="-2500ms" repeatCount="indefinite" calcMode="spline" keyPoints="0; 0.5; 1" keyTimes="0; 0.5; 1" keySplines="0.5, 0.4, 0.5, 0.6; 0.5, 0.4, 0.5, 0.6" > <mpath href="#path" /> </animateMotion> </ellipse></svg>