In the previous article I talked about steps() in CSS animation, and provided a simple example (the ticking second hand of an analog watch). The same core techniques can be used for more complex animation, including a cartoon figure’s walk cycle.

Stack

Traditional cartoon animation creates the impression of motion by showing a series of quick sequenced drawings. During the design and creation phase of the animation these drawings are stacked vertically in “onionskin” layer, allowing the artist to compare them quickly. The same can be achieved by placing drawings on different layers in a modern illustration tool like , as shown in Figure 1:

Figure 1: Stacked figure drawings

I’ll be exporting the drawings as an in order to take advantage of the format’s small (the final size of the optimized file is just over 13K) scaleless nature, but the same technique could be used with a bitmap image.

Walk

Extending the traditional method, the individual drawings are then distributed in a horizontal “filmstrip”, shown in Figure 2:

Figure 2: Figure drawings distributed into even “frames”

The sequence remains the same, but now “reads” from left to right.

The “canvas” area is extended to cover all of the drawings. In this case, each individual “frame” has an area of 250 × 320 pixels.

Step

Our next task is to switch quickly between one drawing and the next, like film running through a camera. Ideally, we would be able to animate the viewBox to move quickly across the scene from one “frame” to the next, but unfortunately we can’t yet animate that with . Instead, we’ll create a container element that is the same aspect ratio as one of the drawings, and apply the exported SVG as a background-image to an element inside it:

<div id="walk-container">
  <div></div>
</div>

The CSS:

#walk-container {
    display: inline-block;
    position: relative;
    width: 20%;
    padding-bottom: 30%; 
    vertical-align: middle; 
}
#walk-container > div {
    display: inline-block;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-image: url(walk-sequence.svg);
    background-repeat: no-repeat;
}

By default the entire SVG “filmstrip” will be visible inside the inner container. We need to make this image large enough so that only one “frame” is visible. This value will be 100 times the number of frames, expressed as a percentage:

#walk-container > div {
    background-size: 800%;
}

Now we need to move the filmstrip through the limited viewport of the #walk-container. That means moving to the end of the filmstrip, which we can express in a CSS keyframe animation that changes the position of the background:

@keyframes walkanim {
  to { background-position: 100% 0; }
}

To run the animation, we’ll start with this:

#walk-container > div {
    animation: walkanim 2s infinite;
}

The result is not exactly what we’re after. You can see what happens in Figure 3:

Figure 3: Filmstrip sliding inside container

Marching in Place

What we need is the animation moving instantaneously between one frame and the next. To achieve this, we’ll divide the animation into separate steps. That way, each frame will be shown once, with no transition between them. The animation call shown above turns into:

#walk-container > div {
    animation: walkanim 1.4s infinite steps(7);
}

Note that the number of steps is 1 less than the number of drawn frames. The duration of the walk cycle animation will depend on how many frames are on the filmstrip, and will usually require some experimentation.

Stepping Forward

So far what we have is only a figure marching in place. This can work if a background is moving behind the character to impart a sense of motion - think classic Saturday morning cartoons - but in this case we’ll say that we want the character moving from left to right across the entire width of the screen. To achieve this, we can “parent” the animation with another, a technique I previously demonstrated for a hypnosis logo. In this case, the added animation will translate the outer container using % units:

@keyframes stroll {
  from { transform: translateX(-100%); }
  to { transform: translateX(500%); }
}

The time taken for this transformation will depend on how you want the animation to appear: too fast, and the figure will look like they are being pushed by a hurricane, while too slow will make it appear that their feet are slipping on an icy surface.

#walk-container {
  animation: stroll 60s linear infinite;
}

I don’t want the figure’s walk to speed up or slow down at the beginning or end, so I’ve used linear easing for the animation.

Conclusion

Once you understand the principles, it’s possible to use these techniques to create many kinds of complex animation on web pages, which I’ll demonstrate in future articles.

Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.
Check out the CodePen demo for this article at https://codepen.io/dudleystorey/pen/aNxEBg