Skip to main content

Loading Animations: April

· 22 min read

Fourth of twelve animations.


Loading Animations (12 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

Animation

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 />  </defs>  <!-- background -->  <rect />  <!-- drawing of the paths traced by the circles, for debugging -->  <g>    <use />    <use />    <use />    <use />    <use />  </g>  <!-- four circles like this -->  <ellipse>    <!-- animations that move the circle along the path -->    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <animateMotion>      <mpath />    </animateMotion>    <!-- animation that stretches the circle along the x axis -->    <animate />    <!-- animation that stretches the circle along the y axis -->    <animate />  </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 path taken has the shape of a pentagon, along which four circles move. Whenever a vertex is left empty, one of the circles pushes another toward that vertex. The movements follow a clockwise direction.

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

Result



Code

// dimensionsconst width = 200;const height = 200;const xCenter = width / 2;const yCenter = height / 2;// pentagonconst numberOfSides = 5;// verticesconst 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  }]*/

Next, I calculated the sides. They extend beyond the vertices, creating space for the circles to move, as if they were gaining momentum or being pushed.

Result



Code

// dimensionsconst width = 200;const height = 200;const xCenter = width / 2;const yCenter = height / 2;// pentagonconst numberOfSides = 5;// verticesconst 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  }]*/// sidesconst 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 }]*/// left and right vertices positionconst extensionProportion = extension / (1 + 2 * extension);const leftVertice = 0 + extensionProportion; //  0.18749999999999997const rightVertice = 1 - extensionProportion; // 0.8125

With the sides calculated, I defined the paths that the circles follow inside defs. They are referenced by their ids, from motion-path-0 to motion-path-4.

After the rect, which serves as the background, I added five use elements to make the paths visible, since anything defined inside defs isn't rendered by default. The use elements are removed once the animation is completed.

Result



Code

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

Circles and their animations

info

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

Animations that follow the path

Initially, I created the animations for the pushing circle and the pushed circle. The idea was to reuse these animations for the other two circles, only changing their start times.

Animating the pushing circle

Starting with the pushing circle, I used an ellipse element, as it allows setting the radius separately for the x and y axes.

I defined five animateMotion elements, each containing an mpath element that references the paths from #motion-path-0 to #motion-path-4. Each animateMotion has the following attributes:

  • id: ranges from circle_1_path_0 to circle_1_path_4
  • begin: each animation starts when the previous one ends, repeating indefinitely
    • #circle_1_path_0, 0ms; circle_1_path_4.end: 0ms ensures this is the first animation to run, and circle_1_path_4.end makes it run again once circle_1_path_4 finishes
    • #circle_1_path_1 to #circle_1_path_4: each starts when the previous animation ends

The following attributes are the same for all animateMotion elements:

  • dur="8000ms": the animation lasts 40 seconds in the examples, with each animateMotion lasting 1/5 of the total duration, which is eight seconds
  • calcMode="spline": to allow using Bézier curves through the keySplines attribute
  • rotate="auto": so the circle follows the rotation of the path
  • keyTimes, keyPoints, and keySplines: since they work together, I represented their attribute values in a table:
keyTimeskeyPointskeySplines
00.18749999999999997 (left vertex)0.25, 0.75, 1, 1
0.200.42, 0, 0.58, 1
0.310.42, 0, 0.58, 1
0.50.8125 (right vertex)0, 0, 1, 1
10.8125 (right vertex)-

A quick reminder of how they work:

  • keyTimes: defines the specific moments along the animation timeline when the keyPoints occur, ranging from 0 to 1
  • keyPoints: defines where the circle should be along the path, also ranging from 0 to 1
  • keySplines: defines Bézier curves to smooth out the progression between keyPoints

Graphical representation:

keyPointskeyTimes101

  • The x and y axes represent the values of the keyTimes and keyPoints attributes, respectively
  • At the top and on the right, the dark gray lines represent the intervals where the keySplines values are applied

In other words, during the first half of the animation, the circle starts at the left vertex, gains momentum, and quickly moves to the other end of the line, stopping at the right vertex. This way, the next animation starts from the same position, keeping the motion continuous.

In the second half, the circle remains stationary. During this interval, the other pair of circles is animated.

Only the pushing circle animated



Code

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

Animating the pushed circle

Just like with the pushing circle, I used an ellipse element containing five animateMotion elements. Each animateMotion contains an mpath element, but this time it starts by referencing path#motion-path-1, one path ahead of the pushing circle’s animation.

Each animateMotion has the following attributes:

  • id and begin: just like the pushing circle, but using circle_2_ instead of circle_1_
  • dur, calcMode, and rotate: the same as the pushing circle
  • keyTimes, keyPoints, and keySplines:
keyTimeskeyPointskeySplines
00.18749999999999997 (left vertex)0, 0, 1, 1
0.260.18749999999999997 (left vertex)0.25, 0.75, 1, 1
0.3610.42, 0, 0.58, 1
0.50.8125 (right vertex)0.42, 0, 0.58, 1
10.8125 (right vertex)-

Graph representation:

keyPointskeyTimes101

In other words, during the first half of the animation, the circle starts at the left vertex, gets pushed, and quickly moves to the other end of the line, stopping at the right vertex. This way, the next animation starts from the same position, keeping the motion continuous.

In the second half, the circle remains stationary. During this interval, the other pair of circles is animated.

First pair of circles animated



Code

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

Stretching animations

Next, I created animations that distort the circles in some way.

Animating rx and ry of the pushing circle

To convey the idea of momentum and speed, I created two animations that, together, stretch the circles horizontally and vertically.

The animate elements share the same attribute values:

  • repeatCount="indefinite": the animation repeats indefinitely
  • dur="8000ms": the duration is eight seconds in the examples
  • keyTimes="0; 0.2; 0.3; 0.5; 1": defines the specific moments along the animation timeline when the attributeName will assume the specified values, ranging from 0 to 1

For the values attribute:

attributeName="rx"attributeName="ry"Descrição
88Starts round
7.68.4Stretches vertically and shrinks horizontally when gaining momentum
8.47.6Stretches horizontally and shrinks vertically when pushing
88Returns to being round
88Stays round

Only the pushing circle animated



Code

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

Animating rx and ry of the pushed circle

To convey the idea of impact and speed, I created two animations that, together, stretch the circles horizontally and vertically.

The animate elements share the same attribute values:

  • repeatCount="indefinite": the animation repeats indefinitely
  • dur="8000ms": the duration is eight seconds in the examples
  • keyTimes="0; 0.26; 0.36; 0.5; 1": defines the specific moments along the animation timeline when the attributeName will assume the specified values, ranging from 0 to 1

For the values attribute:

attributeName="rx"attributeName="ry"Descrição
88Starts round
88Stays round
7.68.4Stretches vertically and shrinks horizontally on impact
88Returns to being round
88Stays round

First pair of circles animated



Code

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

Animating the second pair of circles

The second pair of circles is basically the same as the first one, with the following differences:

  • The ids of each animateMotion: they are similar to the other circles, but start with circle_3_ and circle_4_
  • The begins of each ellipse animation: the animations start with a half-time delay, -4000ms in the examples
  • The paths of each mpath: the third circle starts at path#motion-path-2, and the fourth one at path#motion-path-3

All circles animated



Code

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

Conclusion

As with the previous animation, I used JavaScript to calculate the values of several attributes, and I also used the graphs that illustrate how the attributes keyTimes, keyPoints, and keySplines work together. This made experimentation much easier throughout the development of the animation.

In addition to applying everything I learned from the previous animations, I used a syncbase value for the first time in the begin attribute. This made managing multiple animateMotion elements used together within the same ellipse element much easier. It’s a tool I plan to use in future animations.

Result



Code

<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"  />  <!-- start: circle 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>  <!-- end: circle 1 -->  <!-- start: circle 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>  <!-- end: circle 2 -->  <!-- start: circle 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>  <!-- end: circle 3 -->  <!-- start: circle 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>  <!-- end: circle 4 --></svg>

Recommended reading