Polygon feature design: SVG animations for fun and profit
The Polygon PlayStation 4 Review and Xbox One Review involved an unprecedented level of coordination between the editorial and product teams at Vox Media. The goal was to create a pair of extremely high touch features to highlight the talents of our writers and video team, while pushing the envelope on longform design.
There were a lot of lessons learned, but the final results speak for themselves.
Initially, we did not consider SVG when approaching the design of the reviews. But we soon realized that the SVG format offers the ability to have delicate line art due to its vector and path capabilities, making it a great fit for our needs. And, as it turns out, not just our aesthetic needs, but our technical needs as well.
Polygon, as a site, is designed to be responsive. However, standard image formats like
png don’t don’t always perform well when asked to enlarge or shrink dimensions as dictated by the user’s browser size. SVGs, on the other hand, take on responsive properties perfectly: vectors can increase or shrink to arbitrary sizes without any loss of fidelity, and animations and operations done on SVG elements adjust relative to its size without any additional work.
But before we could use SVGs, they needed to be created. There were no easy preexisting SVGs of the two consoles that we could grab. They needed to be designed from scratch.
From Illustrator to SVG
Polygon’s designer, Tyson Whiting, painstakingly traced paths to create line art from real life photos of the two consoles. Doing this in Adobe Illustrator is relatively straightforward, though it is somewhat mind-numbing.
After exporting a test line art tracing done in Illustrator for the first time, however, there were a couple issues that needed to be addressed:
Many of the colors, fills, and stroke widths Tyson applied inside Illustrator were exported as inline attributes and styles on the SVG elements.
The actual SVG tags used to replicate Illustrator objects (eg,
rectangle) were not clear, and many times not the one we wanted.
The solution was remarkably simple in its directness, if not in its cleverness: just manually massage Illustrator’s exported SVG files.
Inline styles were moved to a centralized stylesheet that affected all SVGs on the page, and we learned through trial and error what attributes were used by Illustrator to determine which SVG tags were chosen.
A factory line was developed: Tyson, Polygon’s designer, would create and export the SVGs in Illustrator; Ally Palanzi, an intern at Vox Media, would manually go into the SVG and add
group tags and comments to clearly label which elements did what; and finally, I would place and animate SVGs wherever needed.
It wasn’t the fastest process, but ultimately we had a set of well-documented and clean SVGs to use.
Visually controlling SVG paths
The act of "drawing" in an SVG is optical trick caused by manipulating two SVG
path is a single, continuous line described by coordinates contained inside the element. It looks something like this:
Animating that path to draw itself is fundamentally an illusion created by adjusting that path’s
stroke-dasharray property is a whitespace or comma delimited list that controls the dashes and gaps that make up the path. When set to
"10 10", for example, the
path's stroke alternates in a dash of
10 and then a gap of
10. Extrapolating this idea, if the total length of the
path was 10, then that would mean the first "dash" is as long as the
Specifically, this means that there is no visual difference between a path that has no
stroke-dasharray set, and a path with a
stroke-dasharray set where the dash is equal to the
path's total length. Conversely, this also means that the gap after the dash is also the length of
Why is this important?
A second property,
stroke-dashoffset controls the offset of the dashes in the
path. The offset, in this case, means where along the path the first "dash" of the dotted dash created by
stroke-dasharray starts. The default value for
stroke-dashoffset is 1 — meaning, it starts immediately.
What does it mean when
stroke-dashoffset is set to the length of the
It means that the dotted dash starts an entire
path's width away. Or put another way, the gap between the dashes defined by
stroke-dasharray fills the entire length of the
path. Or put in even simpler terms, the
path is visually invisible.
Combining these two properties means that we can control how much of the
path is showing, in a visual sense.
The browser is still drawing and rendering the entire
path. However, due to the placement and length of the dashes and gaps, a
stroke-dasharray equal to the length of the
path combined with
stroke-dashoffset's of varying lengths will create the visual illusion of a partial stroke.
SVG path animation
As of this post, there is not a reliable way to determine the specific moment when a CSS transition has finished. It’s possible to fake it by using a
setTimeout equal to the duration of the transition, but by doing so, it’s taken on faith that the transition wouldn’t be slightly slower or faster than the desired duration.
In any case, animating the property with either the CSS or the interval approach works something like the following pseudocode:
for every path in an svg:
store the results of getTotalLength()
set stroke-dasharray equal to totalLength + " " + totalLength
set stroke-dashoffset equal to totalLength
animate method will differ based on the approach used to change the values of
stroke-dashoffset. With a CSS transition approach,
animate would set
transition to something like:
stroke-dashoffset 2s ease-in-out
Then, after setting
stroke-dashoffset to 0 for each
path, the browser will automatically animate that value change via the specified CSS transition.
As mentioned above, this a great and performant way of doing things if the specific timing of when the transition finishes is not important. This gets tricky, however, if you want to chain together animations — or have things happen only after specific animations are finished.
But, there’s one major problem with this approach: the
draw method fires in ignorance of the browser’s render cycle, resulting in needless calls. In practical terms, the browser is doing more work than it needs to, thereby possibly lowering the FPS of the browser’s rendering, and making the animation appear slow.
requestAnimationFrame. There are great resources out around the web already explaining the hows and whys of
Using requestAnimationFrame, the above code now looks something like this:
Duration based vs frame-count based animation
There are two primary ways to determining how long an animation should run; an explicit duration, or a flexible frame count. There are benefits to each approach. The SVG animations on Polygon’s reviews primarily used the frame-count approach rather than setting an explicit animation duration.
Duration-based animation is the approach the code chunk above uses to animate a path. Given a desired duration (in the above case, 2000ms), the animation should run for exactly that duration. "Frames" are calculated by the proportion of elapsed time as compared to the total duration.
This has one big drawback: on slower computers, FPS dips result in skipped frames.
Imagine that in an ideal 60 FPS scenario,
requestAnimationFrame is called 60 times per second. This is fine. That means the animated SVG path’s
stroke-dashoffset is being changed 60 times a second — more than enough for it to appear smoothly animated to the human eye. However, if there’s a dip in FPS — say your computer’s hard drive suddenly starts thrashing and everything slows — then suddenly
requestAnimationFrame is only being called 15 times a second. And because we use elapsed time as the determining factor for
stroke-dashoffset, the visual result is one of dropped frames.
The animation appears to skip around.
The alternate approach, then, is to stop using elapsed time and use a different metric. In a frame-count strategy, we rely on the fact that the browser will self-impose a FPS cap, and simply animate
stroke-dashoffset based on the amount of frames elapsed. The above code chunk would look something like this:
Done this way, if there is ever an FPS dip, the visual impact on the animation is that of a slowdown, rather than a frame skip.
And in the case of Polygon’s PS4 and Xbox One SVG animations, it was deemed that the smoothness of the animations was more important than the specific amount of time that the animations took to run.
Stay tuned for more news on Metronome!
Lastly: Come work with Vox Product! We are hiring.