Skip to main content

Loading Animations: May

· 12 min read

Fifth 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

The animation is a Newton's Cradle, 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 />  </defs>  <!-- background -->  <rect />  <!-- drawing of the paths traced by the circles, for debugging -->  <g>    <use />    <use />    <use />    <use />  </g>  <!-- circles with different animations -->  <ellipse />  <ellipse />  <ellipse />  <ellipse />  <ellipse />  <ellipse />  <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

Inside defs, I defined the paths that the circles follow. They are referenced by their respective IDs.

  • #left-arc and #right-arc: represent the pendulum motion of circles 1 and 5
  • #left-line and #right-line: represent a slight impact movement of circles 2 and 4

After the rect, which is the background, I defined use elements to visualize the paths, since elements defined within defs are not rendered. These use elements are removed upon the animation’s completion.

Result



Code

<svg>  <defs>    <path id="left-arc" d="M68,115 Q38,115 38,85" />    <path id="right-arc" d="M132,115 Q162,115 162,85" />    <path id="left-line" d="M84,115 L83.2,115" />    <path id="right-line" d="M116,115 116.8,115" />  </defs>  <rect />  <g fill="none" stroke="lightgray" stroke-width="1">    <use href="#left-arc" />    <use href="#right-arc" />    <use href="#left-line" />    <use href="#right-line" />  </g></svg>

Circles and their animations

info

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

Animations that follow the path

Initially, I created the animations for circles 1 and 2. My intention was to mirror these animations for circles 4 and 5. Circle 3 does not have an animation.

Animating circle 1

I used an ellipse element, as it allows setting the radius for the x and y axes separately. The mpath element references path#left-arc, and the animateMotion element defines the animation.

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

  • id="circle_left_arc": ID used in the begin attribute of other animations.
  • begin="0; circle_right_arc.end": the animation starts immediately and also when circle 5’s animation ends.
  • dur="10000ms": duration is 10 seconds for the examples.
  • calcMode="spline": to use Bézier curves in the keySplines attribute.
  • rotate="auto": ensures the circle follows the rotation of the path, maintaining correct orientation.
  • fill="freeze": keeps the circle in its final animation position.

Since they work together, I represented the values of the keyTimes, keyPoints, and keySplines attributes in a table:

keyTimeskeyPointskeySplines
000.1, 0.7, 1, 1
0.510.7, 0.1, 1, 1
10-

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

In other words, in the first half of the animation, the circle moves from right to left following a Bézier curve, starting fast and ending slow. In the second half, it moves back from left to right, starting slow and ending fast.

Circle 1 animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />  </g>  <ellipse rx="8" ry="8" fill="black">    <animateMotion      id="circle_left_arc"      begin="0; circle_right_arc.end"      dur="10000ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      calcMode="spline"      keySplines="0.1,0.7,1,1; 0.7,0.1,1,1"      rotate="auto"      fill="freeze"    >      <mpath href="#left-arc" />    </animateMotion>  </ellipse></svg>

Animating circle 2

I used an ellipse element. The mpath references path#left-line, and animateMotion defines the animation.

In the animateMotion element, I defined:

  • id="circle_left_line": ID used in the begin attribute of other animations.
  • begin="0; circle_right_arc.end": starts immediately and also when circle 5’s animation ends.
  • dur="2000ms": 2-second duration for the examples.
  • rotate="auto": ensures the circle follows the rotation of the path.
  • fill="freeze": maintains the final animation position.

Values represented in a table:

keyTimeskeyPoints
00
0.51
10

So, in the first half, the circle moves from right to left linearly. In the second half, it moves back from left to right, also linearly.

I also added circle 3, which has no animation.

Circles 1, 2, and 3 animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />  </g>  <ellipse />  <ellipse rx="8" ry="8" fill="black">    <animateMotion      id="circle_left_line"      begin="0; circle_right_arc.end"      dur="2000ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      rotate="auto"      fill="freeze"    >      <mpath href="#left-line" />    </animateMotion>  </ellipse>  <ellipse rx="8" ry="8" cx="100" cy="115" /></svg>

Animating circle 4

Animating circle 4 required two ellipse elements:

  • One actually animates, it starts hidden and becomes visible when circle 1’s animation ends.
  • The other is visible initially and becomes hidden once circle 1’s animation ends.

This approach helps with positioning and animating circle 4, since setting an element's x,y position changes the animateMotion origin point (point 0,0 becomes x,y, not the top-left of the SVG).

The visible-to-hidden ellipse starts with a black fill and turns transparent using a set element when circle 1’s animation ends.

The hidden-to-visible ellipse starts transparent and turns black via set. It begins invisible because it sits at 0,0 before the animation starts.

The mpath references path#right-line, and animateMotion defines the animation.

animateMotion attributes:

  • id="circle_right_line": ID used in the begin attributes.
  • begin="circle_left_arc.end": starts when circle 1’s animation ends.
  • dur="2000ms": duration is 2 seconds.
  • rotate="auto": follows the path’s rotation.
  • fill="freeze": keeps the final position.

Values represented in a table:

keyTimeskeyPoints
00
0.51
10

So, in the first half, the circle moves left to right linearly. In the second half, it moves right to left linearly.

Circles 1, 2, 3, and 4 animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />  </g>  <ellipse />  <ellipse />  <ellipse />  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_right_line"      begin="circle_left_arc.end"      dur="2000ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      rotate="auto"      fill="freeze"    >      <mpath href="#right-line" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="116" cy="115" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse></svg>

Animating circle 5

The same approach as circle 4 was used for circle 5, with two ellipse elements.

The initially visible ellipse starts black and becomes transparent when circle 1’s animation ends via a set element.

The initially hidden one starts transparent and becomes black via set. It stays at 0,0 before the animation begins.

The mpath references path#right-arc, and animateMotion defines the animation.

Attributes for animateMotion:

  • id="circle_right_arc": used in the begin attribute.
  • begin="circle_left_arc.end": starts immediately when circle 1 ends.
  • dur="10000ms": 10-second duration for examples.
  • calcMode="spline": allows use of Bézier curves in keySplines.
  • rotate="auto": ensures proper path rotation.
  • fill="freeze": retains final animation state.

Values represented in a table:

keyTimeskeyPointskeySplines
000.1, 0.7, 1, 1
0.510.7, 0.1, 1, 1
10-

So, in the first half, the circle moves left to right with a Bézier curve, starting fast and ending slow. In the second half, it moves right to left, starting slow and ending fast.

All circles animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />  </g>  <ellipse />  <ellipse />  <ellipse />  <ellipse />  <ellipse />  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_right_arc"      begin="circle_left_arc.end"      dur="10000ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      calcMode="spline"      keySplines="0.1,0.7,1,1; 0.7,0.1,1,1"      rotate="auto"      fill="freeze"    >      <mpath href="#right-arc" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="132" cy="115" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse></svg>

Stretching animations

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

Animating rx and ry circles 1 and 5

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

The animate elements share the following attributes:

  • dur="10000ms": 10-second duration for the examples.
  • keyTimes="0; 0.25; 0.5; 0.75; 1": defines when the values are applied to the attributeName during the animation.

For the values attribute:

attributeName="rx"attributeName="ry"Description
88Starts round
7.68.4Stretches vertically and shrinks horizontally to express impact
88Returns to round at the top
8.47.6Stretches horizontally and shrinks vertically to express downward speed
88Returns to round when back at the bottom

For the begin attribute, the animate elements start when their neighboring animateMotion starts:

  • begin="circle_left_arc.begin": for circle 1
  • begin="circle_right_arc.begin": for circle 5

All circles animated



Code

<svg>  <defs>    <path />    <path />    <path />    <path />  </defs>  <rect />  <g>    <use />    <use />    <use />    <use />  </g>  <ellipse>    <animateMotion />    <animate      attributeName="rx"      begin="circle_left_arc.begin"      dur="10000ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 7.6; 8; 8.4; 8"    />    <animate      attributeName="ry"      begin="circle_left_arc.begin"      dur="10000ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 8.4; 8; 7.6; 8"    />  </ellipse>  <ellipse />  <ellipse />  <ellipse />  <ellipse />  <ellipse>    <animateMotion />    <animate      attributeName="rx"      begin="circle_right_arc.begin"      dur="10000ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 7.6; 8; 8.4; 8"    />    <animate      attributeName="ry"      begin="circle_right_arc.begin"      dur="10000ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 8.4; 8; 7.6; 8"    />    <set />  </ellipse>  <ellipse /></svg>

Conclusion

In this animation, I was able to use syncbase values again in the begin attribute, allowing animation timing to be coordinated reactively, elements on one side respond to the end of animations on the other.

I also explored using the set element for the first time to change attributes based on syncbase values. This opened up new possibilities to manipulate properties in a targeted way, without needing a full animation when a simple state change is enough.

I intend to continue exploring these tools 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="left-arc" d="M68,115 Q38,115 38,85" />    <path id="right-arc" d="M132,115 Q162,115 162,85" />    <path id="left-line" d="M84,115 L83.2,115" />    <path id="right-line" d="M116,115 116.8,115" />  </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_left_arc"      begin="0; circle_right_arc.end"      dur="700ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      calcMode="spline"      keySplines="0.1,0.7,1,1; 0.7,0.1,1,1"      rotate="auto"      fill="freeze"    >      <mpath href="#left-arc" />    </animateMotion>    <animate      attributeName="rx"      begin="circle_left_arc.begin"      dur="700ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 7.6; 8; 8.4; 8"    />    <animate      attributeName="ry"      begin="circle_left_arc.begin"      dur="700ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 8.4; 8; 7.6; 8"    />  </ellipse>  <!-- end: circle 1 -->  <!-- start: circle 2 -->  <ellipse rx="8" ry="8" fill="black">    <animateMotion      id="circle_left_line"      begin="0; circle_right_arc.end"      dur="150ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      rotate="auto"      fill="freeze"    >      <mpath href="#left-line" />    </animateMotion>  </ellipse>  <!-- end: circle 2 -->  <!-- start: circle 3 -->  <ellipse rx="8" ry="8" cx="100" cy="115" />  <!-- end: circle 3 -->  <!-- start: circle 4 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_right_line"      begin="circle_left_arc.end"      dur="150ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      rotate="auto"      fill="freeze"    >      <mpath href="#right-line" />    </animateMotion>    <set      attributeName="fill"      to="black"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="116" cy="115" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse>  <!-- end: circle 4 -->  <!-- start: circle 5 -->  <ellipse rx="8" ry="8" fill="transparent">    <animateMotion      id="circle_right_arc"      begin="circle_left_arc.end"      dur="700ms"      keyTimes="0; 0.5; 1"      keyPoints="0; 1; 0"      calcMode="spline"      keySplines="0.1,0.7,1,1; 0.7,0.1,1,1"      rotate="auto"      fill="freeze"    >      <mpath href="#right-arc" />    </animateMotion>    <animate      attributeName="rx"      begin="circle_right_arc.begin"      dur="700ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 7.6; 8; 8.4; 8"    />    <animate      attributeName="ry"      begin="circle_right_arc.begin"      dur="700ms"      keyTimes="0; 0.25; 0.5; 0.75; 1"      values="8; 8.4; 8; 7.6; 8"    />    <set      attributeName="fill"      to="black"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse>  <ellipse rx="8" ry="8" cx="132" cy="115" fill="black">    <set      attributeName="fill"      to="transparent"      begin="circle_left_arc.end"      fill="freeze"    />  </ellipse>  <!-- end: circle 5 --></svg>

Recommended reading