Skip to main content

Loading Animations: June

· 20 min read

This is the sixth of twelve animations.


Loading Animations (13 part series)
  1. Introduction
  2. January
  3. February
  4. March
  5. April
  6. May
  7. June
  8. July
  9. August
  10. September
  11. October
  12. November
  13. December

Animation

Final result:

Introduction

I created this animation using SVG, following a structure similar to the previous ones:

<!-- dimensions --><svg>  <defs>    <!-- paths traced by the circles -->    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />  </defs>  <!-- background -->  <rect />  <!-- drawing of the paths traced by the circles, for debugging -->  <g>    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />  </g>  <!-- first circle -->  <ellipse>    <!-- animations that move the circle along the path -->    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>  </ellipse>  <!-- second circle -->  <ellipse>    <!-- animations that move the circle along the path -->    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>  </ellipse>  <!-- four more circles like this, used in the animation -->  <ellipse>    <!-- animations that move the circle along the path -->    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <!-- makes the circle visible on animation start -->    <set />  </ellipse>  <!-- four more circles like this, used as placeholder -->  <ellipse>    <!-- makes the circle invisible on animation start -->    <set />  </ellipse></svg>

How it works

info

To keep the explanation concise, I've left out some elements and attributes from the following code blocks.

Dimensions

I kept the size the same as the previous animations.

Result



Code

<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>

Path

The paths form semicircles, with six circles moving along them. The first circle, which starts at the first point, moves until it reaches the last point, and then returns. The movements follow a clockwise direction.

First, I calculated the position of each circle using JavaScript.

Result



Code

// dimensionsconst width = 200;const height = 200;const xCenter = width / 2;const yCenter = height / 2;// points// - 1 before the first point// - 5 between the points// - 1 after the last pointconst columns = 7;const spacing = width / columns;const points = [];for (let i = 0; i < 6; i++) {  const x = (i + 1) * spacing;  const y = yCenter;  points.push({ x, y });}/*[  { "x": 28.571428571428573, "y": 100 },  { "x": 57.142857142857146, "y": 100 },  { "x": 85.71428571428572,  "y": 100 },  { "x": 114.28571428571429, "y": 100 },  { "x": 142.85714285714286, "y": 100 },  { "x": 171.42857142857144, "y": 100 }]*/

Next, I calculated the semicircles: the upper ones are drawn from left to right, while the lower ones are drawn from right to left. This makes the animation easier to create, since the circles move in a clockwise direction.

The x-axis-rotation attribute has a value of 0, since there is no rotation of the x axis. Since these are semicircles, the large-arc-flag attribute has no effect, so I left it with the value 0. The sweep-flag attribute has a value of 1, so that the arc follows a clockwise direction.

Result



Code

// dimensionsconst width = 200;const height = 200;const xCenter = width / 2;const yCenter = height / 2;// points// - 1 before the first point// - 5 between the points// - 1 after the last pointconst columns = 7;const spacing = width / columns;const points = [];for (let i = 0; i < 6; i++) {  const x = (i + 1) * spacing;  const y = yCenter;  points.push({ x, y });}/*[  { "x": 28.571428571428573, "y": 100 },  { "x": 57.142857142857146, "y": 100 },  { "x": 85.71428571428572,  "y": 100 },  { "x": 114.28571428571429, "y": 100 },  { "x": 142.85714285714286, "y": 100 },  { "x": 171.42857142857144, "y": 100 }]*/// arcsconst radius = spacing / 2;const topArcs = [];for (let i = 0; i < points.length - 1; i++) {  const point = points[i];  const nextPoint = points[i + 1];  topArcs.push(    `M ` + // `move` command      `${point.x}, ${point.y} ` + // x, y      `A ` + // `arc` command      `${radius}, ${radius} ` + // rx, ry      `0 ` + // x-axis-rotation      `0 ` + // large-arc-flag      `1 ` + // sweep-flag      `${nextPoint.x}, ${nextPoint.y} ` // x, y  );}/*[  "M 0,                  100 A 14.285714285714286, 14.285714285714286 0 0 1 28.571428571428573, 100 ",  "M 28.571428571428573, 100 A 14.285714285714286, 14.285714285714286 0 0 1 57.142857142857146, 100 ",  "M 57.142857142857146, 100 A 14.285714285714286, 14.285714285714286 0 0 1 85.71428571428572,  100 ",  "M 85.71428571428572,  100 A 14.285714285714286, 14.285714285714286 0 0 1 114.28571428571429, 100 ",  "M 114.28571428571429, 100 A 14.285714285714286, 14.285714285714286 0 0 1 142.85714285714286, 100 ",  "M 142.85714285714286, 100 A 14.285714285714286, 14.285714285714286 0 0 1 171.42857142857144, 100 "]*/const bottomArcs = [];for (let i = points.length - 1; i >= 1; i--) {  const point = points[i];  const previousPoint = points[i - 1];  bottomArcs.push(    `M ` + // `move` command      `${point.x}, ${point.y} ` + // x, y      `A ` + // `arc` command      `${radius}, ${radius} ` + // rx, ry      `0 ` + // x-axis-rotation      `0 ` + // large-arc-flag      `1 ` + // sweep-flag      `${previousPoint.x}, ${previousPoint.y} ` // x, y  );}/*[  "M 171.42857142857144, 100 A 14.285714285714286, 14.285714285714286 0 0 1 142.85714285714286, 100 ",  "M 142.85714285714286, 100 A 14.285714285714286, 14.285714285714286 0 0 1 114.28571428571429, 100 ",  "M 114.28571428571429, 100 A 14.285714285714286, 14.285714285714286 0 0 1 85.71428571428572,  100 ",  "M 85.71428571428572,  100 A 14.285714285714286, 14.285714285714286 0 0 1 57.142857142857146, 100 ",  "M 57.142857142857146, 100 A 14.285714285714286, 14.285714285714286 0 0 1 28.571428571428573, 100 ",  "M 28.571428571428573, 100 A 14.285714285714286, 14.285714285714286 0 0 1 0,                  100 "]*/

With the arcs calculated, I defined the path elements the circles follow inside defs.

After the rect (which serves as the background), I defined ten use elements to visualize the paths, since elements in defs are not rendered by default. The use elements are removed at the end of the animation.

Result



Code

<svg>  <defs>    <path      id="arc-top-0"      d="M 28.571428571428573, 100 A 14.285714285714286, 14.285714285714286 0 0 1 57.142857142857146, 100 "    />    <path      id="arc-top-1"      d="M 57.142857142857146, 100 A 14.285714285714286, 14.285714285714286 0 0 1 85.71428571428572, 100 "    />    <path      id="arc-top-2"      d="M 85.71428571428572, 100 A 14.285714285714286, 14.285714285714286 0 0 1 114.28571428571429, 100 "    />    <path      id="arc-top-3"      d="M 114.28571428571429, 100 A 14.285714285714286, 14.285714285714286 0 0 1 142.85714285714286, 100 "    />    <path      id="arc-top-4"      d="M 142.85714285714286, 100 A 14.285714285714286, 14.285714285714286 0 0 1 171.42857142857144, 100 "    />    <path      id="arc-bottom-0"      d="M 57.142857142857146, 100 A 14.285714285714286, 14.285714285714286 0 0 1 28.571428571428573, 100 "    />    <path      id="arc-bottom-1"      d="M 85.71428571428572, 100 A 14.285714285714286, 14.285714285714286 0 0 1 57.142857142857146, 100 "    />    <path      id="arc-bottom-2"      d="M 114.28571428571429, 100 A 14.285714285714286, 14.285714285714286 0 0 1 85.71428571428572, 100 "    />    <path      id="arc-bottom-3"      d="M 142.85714285714286, 100 A 14.285714285714286, 14.285714285714286 0 0 1 114.28571428571429, 100 "    />    <path      id="arc-bottom-4"      d="M 171.42857142857144, 100 A 14.285714285714286, 14.285714285714286 0 0 1 142.85714285714286, 100 "    />  </defs>  <rect />  <g fill="none" stroke-width="1" stroke="lightgray">    <use href="#arc-top-0" />    <use href="#arc-top-1" />    <use href="#arc-top-2" />    <use href="#arc-top-3" />    <use href="#arc-top-4" />    <use href="#arc-bottom-0" />    <use href="#arc-bottom-1" />    <use href="#arc-bottom-2" />    <use href="#arc-bottom-3" />    <use href="#arc-bottom-4" />  </g></svg>

Circles and their animations

info

The final animation duration is 0.5 seconds. In this section, the animations last 2 seconds to make them more noticeable.

Animating the first circle

Starting with the first circle, I used an ellipse element.

I defined ten animateMotion elements, five for the top arcs and five for the bottom arcs, each containing an mpath element that references the previously defined paths.

Each animateMotion has the following attributes:

  • id: ranges from circle_0_arc_top_0 to circle_0_arc_top_4, and circle_0_arc_bottom_4 to circle_0_arc_bottom_0
  • begin: each animation begins when the previous one ends, repeating indefinitely
    • #circle_0_arc_top_0, 0; circle_0_arc_bottom_0.end: 0 makes this the first animation to play, starting the movement to the right, and circle_0_arc_bottom_0.end makes the animation play when the animation of the opposite arc ends
    • #circle_0_arc_top_1 to #circle_0_arc_top_4: start their animations when the previous animation ends, making the circle reach the right end
    • #circle_0_arc_bottom_4, circle_0_arc_top_4.end: starts the movement to the left when the animation of the opposite arc ends
    • #circle_0_arc_bottom_3 to #circle_0_arc_bottom_0: start their animations when the previous animation ends, making the circle reach the left end

The following attributes are the same for all animateMotions:

  • dur="2000ms": the animation lasts 2 seconds in the examples
  • fill="freeze": keeps the circle at the end position after the animation completes
  • calcMode="spline": to be able to use Bézier curves in the keySplines attribute
  • keyTimes, keyPoints and keySplines: since they work together, I represented the attribute values in a table:
keyTimeskeyPointskeySplines
000.25, 0.1, 0.25, 1
11-

Remembering how they work:

  • keyTimes: defines at which specific times throughout the animation the keyPoints will occur, ranges from 0 to 1
  • keyPoints: defines where the circle should be along the path; values range from 0 to 1
  • keySplines: defines Bézier curves to smooth the progression between keyPoints

That is, the circle starts at point 0, goes to point 1, and along the way, follows a Bézier curve defined by keySplines.

First circle animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />  </g>  <!-- start: circle 0 -->  <ellipse rx="8" ry="8" fill="black">    <animateMotion      id="circle_0_arc_top_0"      begin="0; circle_0_arc_bottom_0.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-0" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_1"      begin="circle_0_arc_top_0.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-1" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_2"      begin="circle_0_arc_top_1.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-2" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_3"      begin="circle_0_arc_top_2.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-3" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_4"      begin="circle_0_arc_top_3.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-4" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_4"      begin="circle_0_arc_top_4.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-4" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_3"      begin="circle_0_arc_bottom_4.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-3" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_2"      begin="circle_0_arc_bottom_3.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-2" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_1"      begin="circle_0_arc_bottom_2.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-1" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_0"      begin="circle_0_arc_bottom_1.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-0" />    </animateMotion>  </ellipse>  <!-- end: circle 0 --></svg>

Animating the second circle

Just like with the first circle, I used an ellipse element, this time containing two animateMotion elements. Each animateMotion contains an mpath element.

Each animateMotion has the following attributes:

  • id: just like the first circle, but with circle_1_... instead of circle_0_...
  • begin:
    • #circle_1_arc_bottom_0, circle_0_arc_top_0.begin: starts when the first circle passes through the top arc
    • #circle_1_arc_top_0, circle_0_arc_bottom_0.begin: starts when the first circle passes through the bottom arc
    • Other attributes: same as the first circle

First and second circles animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />  </g>  <!-- start: circle 0 -->  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>  </ellipse>  <!-- end: circle 0 -->  <!-- start: circle 1 -->  <ellipse rx="8" ry="8" fill="black">    <animateMotion      id="circle_1_arc_bottom_0"      begin="circle_0_arc_top_0.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-0" />    </animateMotion>    <animateMotion      id="circle_1_arc_top_0"      begin="circle_0_arc_bottom_0.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-0" />    </animateMotion>  </ellipse>  <!-- fim: círculo 1 --></svg>

Animating the rest of the circles

To animate the other circles, two ellipse elements were needed per circle:

  • One that actually has the animation, which starts hidden and becomes visible when its animation starts
  • Another that is only displayed at the beginning and is hidden when the animation of the animation circle starts

I used this approach to simplify positioning and animation, since setting an element's x,y position changes the origin of the animateMotion element to that point, 0,0 becomes x,y, rather than the top-left corner of the SVG.

For the ellipse element that starts visible and becomes invisible, it starts with a black fill and, using a set element, changes to transparent when the animation of the animation circle starts.

For the ellipse element that starts invisible and becomes visible, it starts with a transparent fill and changes to black using a set element. It starts invisible because it assumes the 0,0 position until the animation starts.

In the animateMotion elements, I defined the attributes as follows:

  • id: as in the previous circles, but with circle_2_... to circle_5_...
  • begin: each animation starts when the first circle passes through the opposite arc
  • Other attributes: same as those of the first circle

Defining circle 2 as an example, highlighting the most important attributes of the ellipse, animateMotion and set elements:

<!-- start: circle 2 --><ellipse  rx="8"  ry="8"  fill="transparent">  <animateMotion    id="circle_2_arc_bottom_1"    begin="circle_0_arc_top_1.begin"    dur="500ms"    keyTimes="0; 1"    keyPoints="0; 1"    calcMode="spline"    keySplines="0.25, 0.1, 0.25, 1"    fill="freeze"  >    <mpath href="#arc-bottom-1" />  </animateMotion>  <animateMotion    id="circle_2_arc_top_1"    begin="circle_0_arc_bottom_1.begin"    dur="500ms"    keyTimes="0; 1"    keyPoints="0; 1"    calcMode="spline"    keySplines="0.25, 0.1, 0.25, 1"    fill="freeze"  >    <mpath href="#arc-top-1" />  </animateMotion>  <set    attributeName="fill"    to="black"    begin="circle_2_arc_bottom_1.begin"    fill="freeze"  /></ellipse><ellipse  rx="8"  ry="8"  cx="85.71428571428572"  cy="100"  fill="black">  <set    attributeName="fill"    to="transparent"    begin="circle_2_arc_bottom_1.begin"    fill="freeze"  /></ellipse><!-- fim: círculo 2 -->

All circles animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />    <use />  </g>  <!-- start: circle 0 -->  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>  </ellipse>  <!-- end: circle 0 -->  <!-- start: circle 1 -->  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>  </ellipse>  <!-- fim: círculo 1 -->  <!-- start: circle 2 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_2_arc_bottom_1"      begin="circle_0_arc_top_1.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-1" />    </animateMotion>    <animateMotion      id="circle_2_arc_top_1"      begin="circle_0_arc_bottom_1.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-1" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_2_arc_bottom_1.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="85.71428571428572" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_2_arc_bottom_1.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 2 -->  <!-- start: circle 3 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_3_arc_bottom_2"      begin="circle_0_arc_top_2.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-2" />    </animateMotion>    <animateMotion      id="circle_3_arc_top_2"      begin="circle_0_arc_bottom_2.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-2" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_3_arc_bottom_2.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="114.28571428571429" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_3_arc_bottom_2.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 3 -->  <!-- start: circle 4 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_4_arc_bottom_3"      begin="circle_0_arc_top_3.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-3" />    </animateMotion>    <animateMotion      id="circle_4_arc_top_3"      begin="circle_0_arc_bottom_3.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-3" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_4_arc_bottom_3.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="142.85714285714286" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_4_arc_bottom_3.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 4 -->  <!-- start: circle 5 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_5_arc_bottom_4"      begin="circle_0_arc_top_4.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-4" />    </animateMotion>    <animateMotion      id="circle_5_arc_top_4"      begin="circle_0_arc_bottom_4.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-4" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_5_arc_bottom_4.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="171.42857142857144" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_5_arc_bottom_4.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 5 --></svg>

Conclusion

This is another animation I created while exploring SVG. The idea was to reuse the structure of the previous ones, adjusting the paths and timing of each movement.

By calculating the arcs with JavaScript and using animateMotion with mpath, I was able to organize the movements in a predictable way. The attributes begin, keyTimes, keyPoints, and keySplines helped control the sequence and fluidity of the animation.

Overall, the focus was to better understand how these elements combine to create synchronized movements. The full animation lasts half a second, but the two-second tests make it easier to visualize what's happening.

I continue to experiment with new ways to explore declarative SVG.

Result



Code

<svg  xmlns="http://www.w3.org/2000/svg"  viewBox="0 0 200 200"  width="200"  height="200">  <defs>    <path      id="arc-top-0"      d="M 28.571428571428573, 100 A 14.285714285714286, 14.285714285714286 0 0 1 57.142857142857146, 100 "    />    <path      id="arc-top-1"      d="M 57.142857142857146, 100 A 14.285714285714286, 14.285714285714286 0 0 1 85.71428571428572, 100 "    />    <path      id="arc-top-2"      d="M 85.71428571428572, 100 A 14.285714285714286, 14.285714285714286 0 0 1 114.28571428571429, 100 "    />    <path      id="arc-top-3"      d="M 114.28571428571429, 100 A 14.285714285714286, 14.285714285714286 0 0 1 142.85714285714286, 100 "    />    <path      id="arc-top-4"      d="M 142.85714285714286, 100 A 14.285714285714286, 14.285714285714286 0 0 1 171.42857142857144, 100 "    />    <path      id="arc-bottom-0"      d="M 57.142857142857146, 100 A 14.285714285714286, 14.285714285714286 0 0 1 28.571428571428573, 100 "    />    <path      id="arc-bottom-1"      d="M 85.71428571428572, 100 A 14.285714285714286, 14.285714285714286 0 0 1 57.142857142857146, 100 "    />    <path      id="arc-bottom-2"      d="M 114.28571428571429, 100 A 14.285714285714286, 14.285714285714286 0 0 1 85.71428571428572, 100 "    />    <path      id="arc-bottom-3"      d="M 142.85714285714286, 100 A 14.285714285714286, 14.285714285714286 0 0 1 114.28571428571429, 100 "    />    <path      id="arc-bottom-4"      d="M 171.42857142857144, 100 A 14.285714285714286, 14.285714285714286 0 0 1 142.85714285714286, 100 "    />  </defs>  <rect    width="199"    height="199"    x="0.5"    y="0.5"    fill="white"    stroke="lightgray"    stroke-width="1"    rx="6"  />  <g fill="none" stroke-width="1" stroke="lightgray">    <use href="#arc-top-0" />    <use href="#arc-top-1" />    <use href="#arc-top-2" />    <use href="#arc-top-3" />    <use href="#arc-top-4" />    <use href="#arc-bottom-0" />    <use href="#arc-bottom-1" />    <use href="#arc-bottom-2" />    <use href="#arc-bottom-3" />    <use href="#arc-bottom-4" />  </g>  <!-- start: circle 0 -->  <ellipse rx="8" ry="8" fill="black">    <animateMotion      id="circle_0_arc_top_0"      begin="0; circle_0_arc_bottom_0.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-0" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_1"      begin="circle_0_arc_top_0.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-1" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_2"      begin="circle_0_arc_top_1.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-2" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_3"      begin="circle_0_arc_top_2.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-3" />    </animateMotion>    <animateMotion      id="circle_0_arc_top_4"      begin="circle_0_arc_top_3.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-4" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_4"      begin="circle_0_arc_top_4.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-4" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_3"      begin="circle_0_arc_bottom_4.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-3" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_2"      begin="circle_0_arc_bottom_3.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-2" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_1"      begin="circle_0_arc_bottom_2.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-1" />    </animateMotion>    <animateMotion      id="circle_0_arc_bottom_0"      begin="circle_0_arc_bottom_1.end"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-0" />    </animateMotion>  </ellipse>  <!-- end: circle 0 -->  <!-- start: circle 1 -->  <ellipse rx="8" ry="8" fill="black">    <animateMotion      id="circle_1_arc_bottom_0"      begin="circle_0_arc_top_0.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-0" />    </animateMotion>    <animateMotion      id="circle_1_arc_top_0"      begin="circle_0_arc_bottom_0.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-0" />    </animateMotion>  </ellipse>  <!-- fim: círculo 1 -->  <!-- start: circle 2 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_2_arc_bottom_1"      begin="circle_0_arc_top_1.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-1" />    </animateMotion>    <animateMotion      id="circle_2_arc_top_1"      begin="circle_0_arc_bottom_1.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-1" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_2_arc_bottom_1.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="85.71428571428572" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_2_arc_bottom_1.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 2 -->  <!-- start: circle 3 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_3_arc_bottom_2"      begin="circle_0_arc_top_2.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-2" />    </animateMotion>    <animateMotion      id="circle_3_arc_top_2"      begin="circle_0_arc_bottom_2.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-2" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_3_arc_bottom_2.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="114.28571428571429" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_3_arc_bottom_2.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 3 -->  <!-- start: circle 4 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_4_arc_bottom_3"      begin="circle_0_arc_top_3.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-3" />    </animateMotion>    <animateMotion      id="circle_4_arc_top_3"      begin="circle_0_arc_bottom_3.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-3" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_4_arc_bottom_3.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="142.85714285714286" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_4_arc_bottom_3.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 4 -->  <!-- start: circle 5 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_5_arc_bottom_4"      begin="circle_0_arc_top_4.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-bottom-4" />    </animateMotion>    <animateMotion      id="circle_5_arc_top_4"      begin="circle_0_arc_bottom_4.begin"      dur="500ms"      keyTimes="0; 1"      keyPoints="0; 1"      calcMode="spline"      keySplines="0.25, 0.1, 0.25, 1"      fill="freeze"    >      <mpath href="#arc-top-4" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_5_arc_bottom_4.begin"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="171.42857142857144" cy="100" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_5_arc_bottom_4.begin"      fill="freeze"    />  </ellipse>  <!-- fim: círculo 5 --></svg>

Recommended reading