Putting Gears In Motion: Animating Cars With HTML And SVG — Smashing Magazine

Putting Gears In Motion: Animating Cars With HTML And SVG

About The Author

Jamstack Developer / Technical Content Writer. After all is said and done, structure + order = fun.
More about
Paul ↬

Email Newsletter

SVG <animateMotion> provides a way to define how an element moves along a motion path. In this article, Paul Scanlon shares an idea of how to use it by animating race cars in an infinite loop as easy as one-two-three!

Hello! And if you like HTML, you’ve come to the right place!

I love HTML. As an old-school front-end developer, I think it’s a hugely underrated skill. I’ve been writing HTML since ~2005, and today the browser alone can almost do all the things Flash could do nearly two decades ago!

One such trick HTML now has is called — those familiar with Flash will remember this as The Motion Guide. I found this video from 14 years ago, but the method existed for a while before that:

The idea is, you create a path for elements to follow… and that’s it!

Here’s an example of what you can do with <animateMotion>:

If you take a look at the MDN Docs, you’ll see a simple example of a red circle following a path on an infinite loop. The race cars in the live preview follow the same simple rules, and it works just like this!

SVG Using animateMotion

Here’s a simplified version which I’ll use to explain some of the finer details.

Note: I’ve removed some of the path values for brevity, but you can see src for the below snippet at simple-version.html.)

<!DOCTYPE html>
<html>
  <head>
    <title>Simple Example</title>
  </head>
  <body>
    <main>
      <svg viewBox="0 0 307 184" >
        <g id="track">
          <g id="track-lines">
            <path fill="none" stroke="#facc15" d="M167.88,111.3..." />
          </g>

          <g id="pink-car">
            <animateMotion dur="4s" repeatCount="indefinite" rotate="auto" path="M167.88,111.3..." />
            <path fill="#EC4899" d="M13.71,18.65c0.25-0.5..." />
          </g>
        </g>
      </svg>
    </main>
  </body>
</html>

The first thing to look at is the <g> element with the id of track-lines. This is the yellow dashed line that represents the path the car will follow.

You’ll also see another <g> element with the id of pink-car. Within this group is the <animateMotion> element. It has an attribute of path. The numbers used to form this path are the same as the numbers that form the track-lines. An <animateMotion> element is invisible, and its only purpose is to provide a path for an element to follow.

Speaking of which, below the <animateMotion> element is another <path> element, this is the pink car, and it will follow the path of its nearest neighbor.

animateMotion Attributes

There’s some additional attributes that the <animateMotion> element accepts; these are as follows:

The MDN Docs show the <animateMotion> element as a child of an Svg <circle> shape e.g:

Whilst this approach works for shapes, it will only work if the element can accept a child. The SVG path element can’t, so wrapping everything in the <g> element allows HTML to work out where the coordinate system should start and which elements should follow the path. Sneaky ay!

And that’s it. I designed the track and the other elements seen on the preview link in Adobe Illustrator and exported the whole thing as an SVG. I then did a little bit of manual refactoring to ensure the cars were adjacent to an <animateMotion> element. Et voilà! A race track!

One small snag, the <animateMotion> element doesn’t natively observe prefers-reduce-motion. To work around this in the preview I’ve added a media query that sets any element with the class name of car to display: none;. Not ideal, but it is at least motion safe!

I hope you’ve enjoyed this post, and if you have any questions, please come and find me on Twitter. @PaulieScanlon, oh and if you’re a better illustrator than I am, please, feel free to re-design the race track and cars, and I’ll be happy to convert it into code!

See you around the internet!

This content was originally published here.