Skip to main content

Loading Animations: September

· 22 min read

Ninth 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 in SVG, following a similar structure to the previous ones:

<!-- size definitions --><svg>  <!-- background -->  <rect></rect>  <!-- visualization of paths -->  <path></path>  <!-- one circle that moves horizontally -->  <ellipse>    <!-- movement animations -->    <animateMotion></animateMotion>    <animateMotion></animateMotion>    <!-- deformation animations -->    <animate></animate>    <animate></animate>  </ellipse>  <!-- eight circles that move vertically -->  <ellipse>    <!-- movement animations -->    <animateMotion></animateMotion>    <!-- deformation animations -->    <animate></animate>    <animate></animate>    <!-- visibility change -->    <set></set>  </ellipse>  <!-- eight static circles -->  <ellipse>    <!-- visibility change -->    <set></set>  </ellipse></svg>

How it works

info

I've omitted some elements and attributes in the following blocks to keep the explanation more concise.

Size

I kept the same size 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>

Paths

The animation uses nine paths:

  • 1 horizontal path: the circle moves from one end to the other repeatedly.
  • 8 vertical paths: four upper and four lower, where each circle moves deviating from the circle that follows the horizontal path.

After the rect (background), I defined a path to visualize the paths. The path element is removed in the final version of the animation.

<svg>  <rect />  <path stroke="lightgray" d=""></path></svg>

Horizontal path

  • Horizontal distance from edges: 1/6 of the width, 200 / 6 = 33.3333.
  • Vertical position: 1/2 of the height, 200 / 2 = 100.

Horizontal coordinates:

  • Left: x = 0 + 33.3333 = 33.3333, y = 100, where 0 is the left edge. This is an addition, since the coordinate is to the right of the edge.
  • Right: x = 200 - 33.3333 = 166.6666, y = 100, where 200 is the right edge. This is a subtraction, since the coordinate is to the left of the edge.


<svg>  <rect />  <path    stroke="lightgray"    d="      M 33.3333, 100 L 166.6666, 100    "  ></path></svg>

Vertical paths

  • Horizontal distance from edges: 1/3 of the width, 200 / 3 = 66.6666. In other words, the vertical paths are one-third from the center.
  • Gutter spacing: 66.6666 / 3 = 22.2222.

For the top and bottom vertical x coordinates:

  • x = 66.6666 + 0 * 22.2222 = 66.6666
  • x = 66.6666 + 1 * 22.2222 = 88.8888
  • x = 66.6666 + 2 * 22.2222 = 111.1111
  • x = 66.6666 + 3 * 22.2222 = 133.3333


  • Vertical distance: equal to the gutter.
  • Start: 1/2 gutter above/below the vertical center.
  • End: 1/7 of the height above/below the vertical center.

For the upper vertical y coordinates:

  • y = (200 / 2) - (22.2222 / 2) = 88.8888, vertical center minus 1/2 gutter.
  • y = (200 / 2) - (200 / 7) = 71.4285, vertical center minus 1/7 of the height.

These are subtractions, since the coordinates are above the vertical center.



<svg>  <rect />  <path    stroke="lightgray"    d="      M 33.3333,  100     L 166.6666, 100      M 66.6666,  88.8888 L 66.6666,  71.4285      M 88.8888,  88.8888 L 88.8888,  71.4285      M 111.1111, 88.8888 L 111.1111, 71.4285      M 133.3333, 88.8888 L 133.3333, 71.4285    "  ></path></svg>

For the lower vertical y coordinates:

  • y = (200 / 2) + (22.2222 / 2) = 111.1111, vertical center plus 1/2 gutter.
  • y = (200 / 2) + (200 / 7) = 128.5714, vertical center plus 1/7 of the height.

These are sums, since the coordinates are below the vertical center.



<svg>  <rect />  <path    stroke="lightgray"    d="      M 33.3333,  100      L 166.6666, 100      M 66.6666,  88.8888  L 66.6666,  71.4285      M 88.8888,  88.8888  L 88.8888,  71.4285      M 111.1111, 88.8888  L 111.1111, 71.4285      M 133.3333, 88.8888  L 133.3333, 71.4285      M 66.6666,  111.1111 L 66.6666,  128.5714      M 88.8888,  111.1111 L 88.8888,  128.5714      M 111.1111, 111.1111 L 111.1111, 128.5714      M 133.3333, 111.1111 L 133.3333, 128.5714    "  ></path></svg>

Result



Code

<svg>  <rect />  <path    stroke="lightgray"    d="      M 33.3333,  100      L 166.6666, 100      M 66.6666,  88.8888  L 66.6666,  71.4285      M 88.8888,  88.8888  L 88.8888,  71.4285      M 111.1111, 88.8888  L 111.1111, 71.4285      M 133.3333, 88.8888  L 133.3333, 71.4285      M 66.6666,  111.1111 L 66.6666,  128.5714      M 88.8888,  111.1111 L 88.8888,  128.5714      M 111.1111, 111.1111 L 111.1111, 128.5714      M 133.3333, 111.1111 L 133.3333, 128.5714    "  ></path></svg>

Circles and their animations

info

The full animation lasts 1.5s. In the intermediate examples, I increased it to 15s to highlight the movements.

Animating the horizontal circle movement

I used an ellipse element, which allows you to define the radius on the x and y axes separately. Each movement (back and forth) is controlled by an animateMotion:

  • id: left_to_right and right_to_left
  • begin: each starts when the other ends (continuous loop)
    • #left_to_right, 0ms; right_to_left.end: 0ms makes this the first animation to run, and right_to_left.end makes the animation run when right_to_left ends.
    • #right_to_left, left_to_right.end: the animation runs when left_to_right ends.
  • path: both use the same coordinates, one goes from left to right, and the other from right to left.
    • #left_to_right: M33.3333,100 L166.6666,100
    • #right_to_left: M166.6666,100 L33.3333,100

Common attributes:

  • dur="7500ms": 7.5s forward + 7.5s backward = 15s (total duration)
  • 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.42, 0, 0.58, 1
110.42, 0, 0.58, 1

Here's how they work:

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

In other words, both animateMotions take the circle from the beginning to the end of their respective paths, using a Bézier curve that starts slowly, accelerates in the middle, and decelerates at the end.

Horizontal circle animated



Code

<svg>  <rect />  <path></path>  <ellipse rx="8" ry="8">    <animateMotion      id="left_to_right"      path="M33.3333,100 L166.6666,100"      dur="750ms"      begin="0ms; right_to_left.end"      calcMode="spline"      keyPoints="0; 1"      keyTimes="0; 1"      keySplines="0.42, 0, 0.58, 1"    ></animateMotion>    <animateMotion      id="right_to_left"      path="M166.6666,100 L33.3333,100"      dur="750ms"      begin="left_to_right.end"      calcMode="spline"      keyPoints="0; 1"      keyTimes="0; 1"      keySplines="0.42, 0, 0.58, 1"    ></animateMotion>  </ellipse></svg>

Animating the vertical circles movement

Each circle requires two ellipse elements:

  • Animated, starts invisible, becomes visible when animating (transparent -> black).
  • Static, starts visible, disappears when the animating animation begins (black -> transparent).

Visibility control is done via set.

For the animated circles, I used eight ellipse elements containing an animateMotion element, which moves the vertical circle away from the horizontal circle, and a set element, which makes the circle visible.

Each animateMotion has the following attributes:

  • id: upper_1 to upper_4 and lower_1 to lower_4
  • path: uses the coordinates for the vertical paths, defined previously.

For the begin attribute, after experimenting with start times, I used quarters of the horizontal animation duration, starting the cascade. Where 3750 is 1/2 of the horizontal animation:

  • 3750 * (1 / 4) = 937.5
  • 3750 * (2 / 4) = 1875
  • 3750 * (3 / 4) = 2812.5
  • 3750 * (4 / 4) = 3750

That is, when the horizontal circle starts moving from the left edge to the right:

  • The animation for upper_1 and lower_1 should start 937.5ms later
  • upper_2 and lower_2, 18755ms later
  • upper_3 and lower_3, 2812.55ms later
  • upper_4 and lower_4, 37505ms later

And, when the horizontal circle starts moving from the right edge to the left:

  • The animation for upper_4 and lower_4 should start 937.5ms later
  • upper_3 and lower_3, 18755ms later
  • upper_2 and lower_2, 2812.55ms later
  • upper_1 and lower_1, 37505ms after

The following attributes are the same for all animateMotions:

  • dur="3000ms": defines the duration as 3 seconds, 1/5 of the total duration.
  • fill="freeze": keeps the circle in the final position of the animation.
  • calcMode="spline": allows you to use Bézier curves in the keySplines attribute.
  • keyTimes, keyPoints, and keySplines:
keyTimeskeyPointskeySplines
000.42, 0, 0.58, 1
0.510.42, 0, 0.58, 1
10-

In other words, each animateMotion takes the circle from the beginning to the end and back to the beginning of its path, using a Bézier curve that starts slowly, accelerates in the middle, and decelerates at the end.

Each set has the following attributes:

  • begin="<parent id>.begin": when the value should be applied, that is, as soon as the parent's animation starts.

The following attributes are the same for all sets:

  • attributeName="fill": changes the fill attribute.
  • to="black": the value to be applied.
  • fill="freeze": keeps the applied value.
info

I omitted attributes that are the same between elements to keep the explanation concise.

<svg>  <rect />  <path></path>  <!-- start: horizontal circle -->  <ellipse>    <animateMotion id="left_to_right"></animateMotion>    <animateMotion id="right_to_left"></animateMotion>  </ellipse>  <!-- end: horizontal circle -->  <!-- start: upper vertical circle 1 -->  <ellipse fill="transparent">    <animateMotion      id="upper_1"      path="M66.6666,88.8888 L66.6666,71.4285"      begin="left_to_right.begin+937.5ms; right_to_left.begin+3750ms"    ></animateMotion>    <set to="black" begin="upper_1.begin"></set>  </ellipse>  <!-- end: upper vertical circle 1 -->  <!-- start: lower vertical circle 1 -->  <ellipse fill="transparent">    <animateMotion      id="lower_1"      path="M66.6666,111.1111 L66.6666,128.5714"      begin="left_to_right.begin+937.5ms; right_to_left.begin+3750ms"    ></animateMotion>    <set to="black" begin="lower_1.begin"></set>  </ellipse>  <!-- end: lower vertical circle 1 -->  <!-- start: upper vertical circle 2 -->  <ellipse fill="transparent">    <animateMotion      id="upper_2"      path="M88.8888,88.8888 L88.8888,71.4285"      begin="left_to_right.begin+1875ms; right_to_left.begin+2812.5ms"    ></animateMotion>    <set to="black" begin="upper_2.begin"></set>  </ellipse>  <!-- end: upper vertical circle 2 -->  <!-- start: lower vertical circle 2 -->  <ellipse fill="transparent">    <animateMotion      id="lower_2"      path="M88.8888,111.1111 L88.8888,128.5714"      begin="left_to_right.begin+1875ms; right_to_left.begin+2812.5ms"    ></animateMotion>    <set to="black" begin="lower_2.begin"></set>  </ellipse>  <!-- end: lower vertical circle 2 -->  <!-- start: upper vertical circle 3 -->  <ellipse fill="transparent">    <animateMotion      id="upper_3"      path="M111.1111,88.8888 L111.1111,71.4285"      begin="left_to_right.begin+2812.5ms; right_to_left.begin+1875ms"    ></animateMotion>    <set to="black" begin="upper_3.begin"></set>  </ellipse>  <!-- end: upper vertical circle 3 -->  <!-- start: lower vertical circle 3 -->  <ellipse fill="transparent">    <animateMotion      id="lower_4"      path="M111.1111,111.1111 L111.1111,128.5714"      begin="left_to_right.begin+2812.5ms; right_to_left.begin+1875ms"    ></animateMotion>    <set to="black" begin="lower_4.begin"></set>  </ellipse>  <!-- end: lower vertical circle 3 -->  <!-- start: upper vertical circle 4 -->  <ellipse fill="transparent">    <animateMotion      id="upper_4"      path="M133.3333,88.8888 L133.3333,71.4285"      begin="left_to_right.begin+3750ms; right_to_left.begin+937.5ms"    ></animateMotion>    <set to="black" begin="upper_4.begin"></set>  </ellipse>  <!-- end: upper vertical circle 4 -->  <!-- start: lower vertical circle 4 -->  <ellipse fill="transparent">    <animateMotion      id="lower_4"      path="M133.3333,111.1111 L133.3333,128.5714"      begin="left_to_right.begin+3750ms; right_to_left.begin+937.5ms"    ></animateMotion>    <set to="black" begin="lower_4.begin"></set>  </ellipse>  <!-- end: lower vertical circle 4 --></svg>

For the static circles, I used eight ellipse elements containing a set element, which have the following attributes:

  • begin="<animated circle id>.begin": When the value should be applied, that is, as soon as the animated circle's animation starts.

The following attributes are the same for all sets:

  • attributeName="fill": Changes the fill attribute.
  • to="transparent": The value to be applied.
  • fill="freeze": Keeps the applied value.
info

I omitted attributes that are the same between elements to keep the explanation concise.

<svg>  <rect />  <path></path>  <!-- start: horizontal circle -->  <ellipse>    <animateMotion id="left_to_right"></animateMotion>    <animateMotion id="right_to_left"></animateMotion>  </ellipse>  <!-- end: horizontal circle -->  <!-- start: upper vertical circle 1 -->  <ellipse fill="transparent">    <animateMotion      id="upper_1"      path="M66.6666,88.8888 L66.6666,71.4285"      begin="left_to_right.begin+937.5ms; right_to_left.begin+3750ms"    ></animateMotion>    <set to="black" begin="upper_1.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="upper_1.begin"></set>  </ellipse>  <!-- end: upper vertical circle 1 -->  <!-- start: lower vertical circle 1 -->  <ellipse fill="transparent">    <animateMotion      id="lower_1"      path="M66.6666,111.1111 L66.6666,128.5714"      begin="left_to_right.begin+937.5ms; right_to_left.begin+3750ms"    ></animateMotion>    <set to="black" begin="lower_1.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="lower_1.begin"></set>  </ellipse>  <!-- end: lower vertical circle 1 -->  <!-- start: upper vertical circle 2 -->  <ellipse fill="transparent">    <animateMotion      id="upper_2"      path="M88.8888,88.8888 L88.8888,71.4285"      begin="left_to_right.begin+1875ms; right_to_left.begin+2812.5ms"    ></animateMotion>    <set to="black" begin="upper_2.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="upper_2.begin"></set>  </ellipse>  <!-- end: upper vertical circle 2 -->  <!-- start: lower vertical circle 2 -->  <ellipse fill="transparent">    <animateMotion      id="lower_2"      path="M88.8888,111.1111 L88.8888,128.5714"      begin="left_to_right.begin+1875ms; right_to_left.begin+2812.5ms"    ></animateMotion>    <set to="black" begin="lower_2.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="lower_2.begin"></set>  </ellipse>  <!-- end: lower vertical circle 2 -->  <!-- start: upper vertical circle 3 -->  <ellipse fill="transparent">    <animateMotion      id="upper_3"      path="M111.1111,88.8888 L111.1111,71.4285"      begin="left_to_right.begin+2812.5ms; right_to_left.begin+1875ms"    ></animateMotion>    <set to="black" begin="upper_3.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="upper_3.begin"></set>  </ellipse>  <!-- end: upper vertical circle 3 -->  <!-- start: lower vertical circle 3 -->  <ellipse fill="transparent">    <animateMotion      id="lower_4"      path="M111.1111,111.1111 L111.1111,128.5714"      begin="left_to_right.begin+2812.5ms; right_to_left.begin+1875ms"    ></animateMotion>    <set to="black" begin="lower_4.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="lower_4.begin"></set>  </ellipse>  <!-- end: lower vertical circle 3 -->  <!-- start: upper vertical circle 4 -->  <ellipse fill="transparent">    <animateMotion      id="upper_4"      path="M133.3333,88.8888 L133.3333,71.4285"      begin="left_to_right.begin+3750ms; right_to_left.begin+937.5ms"    ></animateMotion>    <set to="black" begin="upper_4.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="upper_4.begin"></set>  </ellipse>  <!-- end: upper vertical circle 4 -->  <!-- start: lower vertical circle 4 -->  <ellipse fill="transparent">    <animateMotion      id="lower_4"      path="M133.3333,111.1111 L133.3333,128.5714"      begin="left_to_right.begin+3750ms; right_to_left.begin+937.5ms"    ></animateMotion>    <set to="black" begin="lower_4.begin"></set>  </ellipse>  <ellipse fill="black">    <set to="transparent" begin="lower_4.begin"></set>  </ellipse>  <!-- end: lower vertical circle 4 --></svg>

Horizontal and vertical circles animated



Code

<svg>  <rect></rect>  <path></path>  <!-- start: horizontal circle -->  <ellipse>    <animateMotion id="left_to_right"></animateMotion>    <animateMotion id="right_to_left"></animateMotion>  </ellipse>  <!-- end: horizontal circle -->  <!-- start: upper vertical circle 1 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_1"      path="M66.6666,88.8888 L66.6666,71.4285"      dur="3000ms"      begin="left_to_right.begin+937.5ms; right_to_left.begin+3750ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="upper_1.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="66.6666" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_1.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 1 -->  <!-- start: lower vertical circle 1 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_1"      path="M66.6666,111.1111 L66.6666,128.5714"      dur="3000ms"      begin="left_to_right.begin+937.5ms; right_to_left.begin+3750ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="lower_1.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="66.6666" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_1.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 1 -->  <!-- start: upper vertical circle 2 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_2"      path="M88.8888,88.8888 L88.8888,71.4285"      dur="3000ms"      begin="left_to_right.begin+1875ms; right_to_left.begin+2812.5ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="upper_2.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="88.8888" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_2.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 2 -->  <!-- start: lower vertical circle 2 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_2"      path="M88.8888,111.1111 L88.8888,128.5714"      dur="3000ms"      begin="left_to_right.begin+1875ms; right_to_left.begin+2812.5ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="lower_2.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="88.8888" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_2.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 2 -->  <!-- start: upper vertical circle 3 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_3"      path="M111.1111,88.8888 L111.1111,71.4285"      dur="3000ms"      begin="left_to_right.begin+2812.5ms; right_to_left.begin+1875ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="upper_3.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="111.1111" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_3.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 3 -->  <!-- start: lower vertical circle 3 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_3"      path="M111.1111,111.1111 L111.1111,128.5714"      dur="3000ms"      begin="left_to_right.begin+2812.5ms; right_to_left.begin+1875ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="lower_3.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="111.1111" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_3.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 3 -->  <!-- start: upper vertical circle 4 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_4"      path="M133.3333,88.8888 L133.3333,71.4285"      dur="3000ms"      begin="left_to_right.begin+3750ms; right_to_left.begin+937.5ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="upper_4.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="133.3333" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_4.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 4 -->  <!-- start: lower vertical circle 4 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_4"      path="M133.3333,111.1111 L133.3333,128.5714"      dur="3000ms"      begin="left_to_right.begin+3750ms; right_to_left.begin+937.5ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <set      attributeName="fill"      to="black"      begin="lower_4.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="133.3333" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_4.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 4 --></svg>

Animating rx and ry

To convey speed, I added animate to rx and ry, stretching and compressing the circles. The animate elements have the following attributes:

  • dur: The duration is the same as the respective motion animation.
    • Horizontal circle: 7500ms
    • Vertical circles: 3000ms
  • begin:
    • Horizontal circle: `left_to_right.begin; right_to_left.begin, when one of the motion animations begins.
    • Vertical circles: upper_1.begin to upper_4.begin and lower_1.begin to lower_4.begin, when their respective motion animations begin.

The following attributes are the same for all animate:

  • calcMode="spline": to use Bézier curves in the keySplines attribute.
  • attributeName, values, keyTimes, and keySplines are represented together in the table:

For the values attribute:

keyTimesattributeName="rx"attributeName="ry"keySplines
0880.42, 0, 0.58, 1
0.58.47.60.42, 0, 0.58, 1
188-

In other words, the circle starts out round, stretches vertically, shrinks horizontally, and then returns to being round. The transition between each value of rx and ry uses a Bézier curve that starts slowly, accelerates in the middle, and decelerates at the end. In the horizontal circle, the animation has an acceleration effect. In the vertical circles, it has a sudden stop effect before returning to the starting point.

Horizontal and vertical circles animated



Code

info

I omitted attributes that are the same between elements to keep the explanation concise.

<svg>  <rect></rect>  <path></path>  <!-- start: horizontal circle -->  <ellipse>    <animateMotion id="left_to_right"></animateMotion>    <animateMotion id="right_to_left"></animateMotion>    <animate      attributeName="rx"      dur="7500ms"      begin="left_to_right.begin; right_to_left.begin"    ></animate>    <animate      attributeName="ry"      dur="7500ms"      begin="left_to_right.begin; right_to_left.begin"    ></animate>  </ellipse>  <!-- end: horizontal circle -->  <!-- start: upper vertical circle 1 -->  <ellipse>    <animateMotion id="upper_1"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="upper_1.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="upper_1.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: upper vertical circle 1 -->  <!-- start: lower vertical circle 1 -->  <ellipse>    <animateMotion id="lower_1"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="lower_1.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="lower_1.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: lower vertical circle 1 -->  <!-- start: upper vertical circle 2 -->  <ellipse>    <animateMotion id="upper_2"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="upper_2.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="upper_2.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: upper vertical circle 2 -->  <!-- start: lower vertical circle 2 -->  <ellipse>    <animateMotion id="lower_2"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="lower_2.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="lower_2.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: lower vertical circle 2 -->  <!-- start: upper vertical circle 3 -->  <ellipse>    <animateMotion id="upper_3"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="upper_3.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="upper_3.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: upper vertical circle 3 -->  <!-- start: lower vertical circle 3 -->  <ellipse>    <animateMotion id="lower_3"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="lower_3.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="lower_3.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: lower vertical circle 3 -->  <!-- start: upper vertical circle 4 -->  <ellipse>    <animateMotion id="upper_4"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="upper_4.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="upper_4.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: upper vertical circle 4 -->  <!-- start: lower vertical circle 4 -->  <ellipse>    <animateMotion id="lower_4"></animateMotion>    <animate attributeName="rx" dur="3000ms" begin="lower_4.begin"></animate>    <animate attributeName="ry" dur="3000ms" begin="lower_4.begin"></animate>    <set></set>  </ellipse>  <ellipse>    <set></set>  </ellipse>  <!-- end: lower vertical circle 4 --></svg>

Conclusion

This animation was an exercise in combining different SVG techniques: defining trajectories with path, synchronizing movements with animateMotion, controlling visibility with set, and giving more life to elements by animating rx and ry. The result is a simple composition that conveys dynamism, interaction, and rhythm using only native SVG features, without the need for CSS or JavaScript. With this, I completed the ninth of twelve animations in this series.

Result



Code

<svg  xmlns="http://www.w3.org/2000/svg"  viewBox="0 0 200 200"  width="200"  height="200">  <rect    width="199"    height="199"    rx="6"    x="0.5"    y="0.5"    fill="white"    stroke-width="1"    stroke="lightgray"  ></rect>  <!-- start: horizontal circle -->  <ellipse rx="8" ry="8">    <animateMotion      id="left_to_right"      path="M33.3333,100 L166.6666,100"      dur="750ms"      begin="0ms; right_to_left.end"      calcMode="spline"      keyPoints="0; 1"      keyTimes="0; 1"      keySplines="0.42, 0, 0.58, 1"    ></animateMotion>    <animateMotion      id="right_to_left"      path="M166.6666,100 L33.3333,100"      dur="750ms"      begin="left_to_right.end"      calcMode="spline"      keyPoints="0; 1"      keyTimes="0; 1"      keySplines="0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="750ms"      begin="left_to_right.begin; right_to_left.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="750ms"      begin="left_to_right.begin; right_to_left.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>  </ellipse>  <!-- end: horizontal circle -->  <!-- start: upper vertical circle 1 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_1"      path="M66.6666,88.8888 L66.6666,71.4285"      dur="300ms"      begin="left_to_right.begin+93.75ms; right_to_left.begin+375ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="upper_1.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="upper_1.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="upper_1.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="66.6666" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_1.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 1 -->  <!-- start: lower vertical circle 1 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_1"      path="M66.6666,111.1111 L66.6666,128.5714"      dur="300ms"      begin="left_to_right.begin+93.75ms; right_to_left.begin+375ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="lower_1.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="lower_1.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="lower_1.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="66.6666" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_1.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 1 -->  <!-- start: upper vertical circle 2 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_2"      path="M88.8888,88.8888 L88.8888,71.4285"      dur="300ms"      begin="left_to_right.begin+187.5ms; right_to_left.begin+281.25ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="upper_2.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="upper_2.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="upper_2.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="88.8888" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_2.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 2 -->  <!-- start: lower vertical circle 2 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_2"      path="M88.8888,111.1111 L88.8888,128.5714"      dur="300ms"      begin="left_to_right.begin+187.5ms; right_to_left.begin+281.25ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="lower_2.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="lower_2.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="lower_2.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="88.8888" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_2.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 2 -->  <!-- start: upper vertical circle 3 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_3"      path="M111.1111,88.8888 L111.1111,71.4285"      dur="300ms"      begin="left_to_right.begin+281.25ms; right_to_left.begin+187.5ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="upper_3.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="upper_3.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="upper_3.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="111.1111" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_3.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 3 -->  <!-- start: lower vertical circle 3 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_3"      path="M111.1111,111.1111 L111.1111,128.5714"      dur="300ms"      begin="left_to_right.begin+281.25ms; right_to_left.begin+187.5ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="lower_3.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="lower_3.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="lower_3.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="111.1111" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_3.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 3 -->  <!-- start: upper vertical circle 4 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="upper_4"      path="M133.3333,88.8888 L133.3333,71.4285"      dur="300ms"      begin="left_to_right.begin+375ms; right_to_left.begin+93.75ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="upper_4.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="upper_4.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="upper_4.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="133.3333" cy="88.8888">    <set      attributeName="fill"      to="transparent"      begin="upper_4.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: upper vertical circle 4 -->  <!-- start: lower vertical circle 4 -->  <ellipse fill="transparent" rx="8" ry="8">    <animateMotion      id="lower_4"      path="M133.3333,111.1111 L133.3333,128.5714"      dur="300ms"      begin="left_to_right.begin+375ms; right_to_left.begin+93.75ms"      fill="freeze"      calcMode="spline"      keyPoints="0; 1; 0"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animateMotion>    <animate      attributeName="rx"      dur="300ms"      begin="lower_4.begin"      calcMode="spline"      values="8; 8.4; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <animate      attributeName="ry"      dur="300ms"      begin="lower_4.begin"      calcMode="spline"      values="8; 7.6; 8"      keyTimes="0; 0.5; 1"      keySplines="0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1"    ></animate>    <set      attributeName="fill"      to="black"      begin="lower_4.begin"      fill="freeze"    ></set>  </ellipse>  <ellipse fill="black" rx="8" ry="8" cx="133.3333" cy="111.1111">    <set      attributeName="fill"      to="transparent"      begin="lower_4.begin"      fill="freeze"    ></set>  </ellipse>  <!-- end: lower vertical circle 4 --></svg>

Recommended reading