Skip to main content

Loading Animations: February

· 12 min read

Second 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

Result:

Introduction

I created this animation using SVG, following a structure very similar to the January animation:

<!-- dimensions --><svg>  <defs>    <!-- paths traced by the circles -->    <path />    <path />  </defs>  <!-- background -->  <rect />  <!-- drawing of the paths traced by the circles, for debugging -->  <use />  <use />  <!-- left circle -->  <ellipse>    <!-- animation that moves the circle along the path -->    <animateMotion>      <mpath />    </animateMotion>    <!-- animation that stretches the circle along the x axis -->    <animate />    <!-- animation that stretches the circle along the y axis -->    <animate />  </ellipse>  <!-- right circle -->  <ellipse>    <!-- animation that moves the circle along the path -->    <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 it the same as the January animation.

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 two paths that will serve as the paths the circles follow. They will be referenced by their ids, left-motion-path and right-motion-path. The paths are two lines defined using the L command. While the left line is drawn from left to right, the right line is drawn from right to left — this was important to mirror the animations.

It is worth noting that circle and ellipse elements are positioned according to their centers. Therefore, the left path extends to x = 92, which is the center of the rect, x = 100, minus the circle's radius, 8. Meanwhile, the right path extends to x = 108, the center of the rect plus the circle's radius. This way, the circles do not overlap — they only touch.

After the rect, which serves as the background, I defined two use elements to visualize the paths, since elements inside defs are not rendered. The use elements are removed at the end of the animation.

Result



Code

<svg>  <defs>    <path id="left-motion-path" d="M30,100 L92,100" />    <path id="right-motion-path" d="M170,100 L108,100" />  </defs>  <rect />  <use    href="#left-motion-path"    fill="none"    stroke="lightgray"    stroke-width="1"  />  <use    href="#right-motion-path"    fill="none"    stroke="lightgray"    stroke-width="1"  /></svg>

Circles and their animations

info

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

Animations that follow the paths

Initially, I created the animations that define the back-and-forth cycle of the circles. My intention was to create an animation for the left circle that could also be used for the right circle, simply by mirroring it and changing the animation start time. Therefore, it was important to define an animation where, for half the duration, a circle remains still, and for the other half, it moves.

Animating the left circle

Starting with the left circle, I used an ellipse element because it allows defining the radius separately for the x and y axes. The mpath element references path#left-motion-path, while the animateMotion element defines the animation.

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

  • repeatCount="indefinite": the animation repeats indefinitely.
  • dur="10000ms": the duration is 10 seconds for the examples.
  • calcMode="spline": to use Bézier curves in the keySplines attribute.

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

keyTimeskeyPointskeySplines
00.50, 0.8, 1, 1
0.10.350.8, 0, 1, 1
0.210, 0, 1, 1
0.710.42, 0, 0.58, 1
0.800.42, 0, 0.58, 1
0.950.50, 0, 1, 1
10.5-

Reminder on how they work:

  • keyTimes: defines the specific moments during the animation's duration when 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.

To make the animation's behavior clearer to myself, I created a graph using the values from the table:

keyPointskeyTimes101

  • The x and y axes represent the values of the keyTimes and keyPoints attributes, respectively.
  • At the top, the dark gray horizontal line represents the segments of the keySplines attribute, which define Bézier curves:
    1. 0, 0.8, 1, 1: starts fast and slows down towards the end.
    2. 0.8, 0, 1, 1: starts slow and accelerates towards the end.
    3. 0, 0, 1, 1: has linear behavior.
    4. 0.42, 0, 0.58, 1: starts slow, accelerates in the middle, and slows down towards the end.
    5. 0.42, 0, 0.58, 1: same curve as the previous segment.
    6. 0, 0, 1, 1: same curve as the third segment.
  • On the right, the light gray vertical line and the black circle represent the final movement.

Left circle animated



Code

<svg>  <defs>    <path />    <path />  </defs>  <rect />  <use />  <use />  <ellipse rx="8" ry="8" fill="black">    <animateMotion      repeatCount="indefinite"      calcMode="spline"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      keyPoints="0.5; 0.35; 1; 1; 0; 0.5; 0.5"      keySplines="0, 0.8, 1, 1; 0.8, 0, 1, 1; 0, 0, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1"    >      <mpath href="#left-motion-path" />    </animateMotion>  </ellipse></svg>

Animating the right circle

Just like in the left circle, I used an ellipse element, this time with the mpath element referencing the path#right-motion-path.

The attributes of the animateMotion element are the same as those used in the left circle, with the difference that the animation is advanced by half of the cycle time:

  • begin="-5000ms": defines when the animation should start.

The animation is mirrored because the path used was drawn in the opposite direction from the left circle, from right to left.

Right circle animated



Code

<svg>  <defs>    <path />    <path />  </defs>  <rect />  <use />  <use />  <ellipse>    <animateMotion>      <mpath />    </animateMotion>  </ellipse>  <ellipse rx="8" ry="8" fill="black">    <animateMotion      repeatCount="indefinite"      calcMode="spline"      begin="-5000ms"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      keyPoints="0.5; 0.35; 1; 1; 0; 0.5; 0.5"      keySplines="0, 0.8, 1, 1; 0.8, 0, 1, 1; 0, 0, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1"    >      <mpath href="#right-motion-path" />    </animateMotion>  </ellipse></svg>

Result



Code

<svg>  <defs>    <path />    <path />  </defs>  <rect />  <use />  <use />  <ellipse rx="8" ry="8" fill="black">    <animateMotion      repeatCount="indefinite"      calcMode="spline"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      keyPoints="0.5; 0.35; 1; 1; 0; 0.5; 0.5"      keySplines="0, 0.8, 1, 1; 0.8, 0, 1, 1; 0, 0, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1"    >      <mpath href="#left-motion-path" />    </animateMotion>  </ellipse>  <ellipse rx="8" ry="8" fill="black">    <animateMotion      repeatCount="indefinite"      calcMode="spline"      begin="-5000ms"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      keyPoints="0.5; 0.35; 1; 1; 0; 0.5; 0.5"      keySplines="0, 0.8, 1, 1; 0.8, 0, 1, 1; 0, 0, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1"    >      <mpath href="#right-motion-path" />    </animateMotion>  </ellipse></svg>

Stretching Animations

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

Animating rx and ry of the left circle

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

The animate elements have attributes with the same value:

  • repeatCount="indefinite": the animation repeats indefinitely.
  • dur="10000ms": the duration is 10 seconds for the examples.
  • keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1": defines the specific moments during the animation's duration when the values will be set to attributeName, ranging from 0 to 1.

For the values attribute:

attributeName="rx"attributeName="ry"Description
88Starts round
8.47.6Stretches horizontally and shrinks vertically to express speed when gaining momentum
88Returns to being round until the impact with the other circle
88Stays round while stationary
7.68.4Shrinks horizontally and stretches vertically when receiving the impact from the other circle
88Returns to being round until it reaches the middle of the path
88Stays round while stationary

Left circle animated



Code

<svg>  <defs>    <path />    <path />  </defs>  <rect />  <use />  <use />  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animate      attributeName="rx"      repeatCount="indefinite"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 8.4; 8; 8; 7.6; 8; 8"    />    <animate      attributeName="ry"      repeatCount="indefinite"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 7.6; 8; 8; 8.4; 8; 8"    />  </ellipse>  <ellipse>    <animateMotion>      <mpath />    </animateMotion>  </ellipse></svg>

Animating rx and ry of the right circle

The attributes are the same as those used in the left circle, with the difference that the animation is advanced by half of the cycle time:

  • begin="-5000ms": defines when the animation should start.

Right circle animated



Code

<svg>  <defs>    <path />    <path />  </defs>  <rect />  <use />  <use />  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animate />    <animate />  </ellipse>  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animate      attributeName="rx"      repeatCount="indefinite"      begin="-5000ms"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 8.4; 8; 8; 7.6; 8; 8"    />    <animate      attributeName="ry"      repeatCount="indefinite"      begin="-5000ms"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 7.6; 8; 8; 8.4; 8; 8"    />  </ellipse></svg>

Result



Code

<svg>  <defs>    <path />    <path />  </defs>  <rect />  <use />  <use />  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animate      attributeName="rx"      repeatCount="indefinite"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 8.4; 8; 8; 7.6; 8; 8"    />    <animate      attributeName="ry"      repeatCount="indefinite"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 7.6; 8; 8; 8.4; 8; 8"    />  </ellipse>  <ellipse>    <animateMotion>      <mpath />    </animateMotion>    <animate      attributeName="rx"      repeatCount="indefinite"      begin="-5000ms"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 8.4; 8; 8; 7.6; 8; 8"    />    <animate      attributeName="ry"      repeatCount="indefinite"      begin="-5000ms"      dur="10000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 7.6; 8; 8; 8.4; 8; 8"    />  </ellipse></svg>

Conclusion

Just like the January animation, the February one was also fun to create, as it is the first to involve interaction between circles — something that will become common in the upcoming posts of the series. This time, I didn't use any new elements or attributes, but I was able to apply everything I learned from the January animation.

The biggest challenge was creating a perfect animation loop between the circles. Creating the graph that illustrates how the keyTimes, keyPoints, and keySplines attributes work together was crucial for experimenting with different values, something I will definitely 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="left-motion-path" d="M30,100 L92,100" />    <path id="right-motion-path" d="M170,100 L108,100" />  </defs>  <rect    width="199"    height="199"    x="0.5"    y="0.5"    fill="white"    stroke="lightgray"    stroke-width="1"    rx="6"  />  <ellipse rx="8" ry="8" fill="black">    <animateMotion      repeatCount="indefinite"      calcMode="spline"      dur="2000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      keyPoints="0.5; 0.35; 1; 1; 0; 0.5; 0.5"      keySplines="0, 0.8, 1, 1; 0.8, 0, 1, 1; 0, 0, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1"    >      <mpath href="#left-motion-path" />    </animateMotion>    <animate      attributeName="rx"      repeatCount="indefinite"      dur="2000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 8.4; 8; 8; 7.6; 8; 8"    />    <animate      attributeName="ry"      repeatCount="indefinite"      dur="2000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 7.6; 8; 8; 8.4; 8; 8"    />  </ellipse>  <ellipse rx="8" ry="8" fill="black">    <animateMotion      repeatCount="indefinite"      calcMode="spline"      begin="-1000ms"      dur="2000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      keyPoints="0.5; 0.35; 1; 1; 0; 0.5; 0.5"      keySplines="0, 0.8, 1, 1; 0.8, 0, 1, 1; 0, 0, 1, 1; 0.42, 0, 0.58, 1; 0.42, 0, 0.58, 1; 0, 0, 1, 1"    >      <mpath href="#right-motion-path" />    </animateMotion>    <animate      attributeName="rx"      repeatCount="indefinite"      begin="-1000ms"      dur="2000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 8.4; 8; 8; 7.6; 8; 8"    />    <animate      attributeName="ry"      repeatCount="indefinite"      begin="-1000ms"      dur="2000ms"      keyTimes="0; 0.1; 0.2; 0.7; 0.8; 0.95; 1"      values="8; 7.6; 8; 8; 8.4; 8; 8"    />  </ellipse></svg>

Recommended reading