Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead
The SMIL specification was introduced by the W3C in 1998 for synchronizing multimedia. This was long before CSS animations or JavaScript-based animation libraries were available. It was built into SVG 1.1, which is why we can still use it there today.
Now, you might’ve heard that SMIL is dead. However, it’s alive and well since Google reversed a decision to deprecate the technology almost a decade ago. It remains a terrific choice for designers and developers who want simple, semantic ways to add animations to their designs.
Tip: There’s now a website where you can see all my Toon Titles.
Mike loves ’90s animation — especially Disney’s) Duck Tales). Unsurprisingly, my taste in cartoons stretches back a little further to Hanna-Barbera shows like Dastardly and Muttley in Their Flying Machines, Scooby-Doo, The Perils of Penelope Pitstop, Wacky Races, and, of course, The Yogi Bear Show. So, to explain how this era of animation relates to SVG, I’ll be adding SMIL animations in SVG to title cards from some classic Yogi Bear cartoons.
Fundamentally, animation changes how an element looks and where it appears over time using a few basic techniques. That might be simply shifting an element up or down, left or right, to create the appearance of motion, like Yogi Bear moving across the screen.
Rotating objects around a fixed point can create everything, from simple spinning effects to natural-looking movements of totally normal things, like a bear under a parachute falling from the sky.
Scaling makes an element grow, shrink, or stretch, which can add drama, create perspective, or simulate depth.
Changing colour and transitioning opacity can add atmosphere, create a mood, and enhance visual storytelling. Just these basic principles can create animations that attract attention and improve someone’s experience using a design.
These results are all achievable using CSS animations, but some SVG properties can’t be animated using CSS. Luckily, we can do more — and have much more fun — using SMIL animations in SVG. We can combine complex animations, move objects along paths, and control when they start, stop, and everything in between.
Animations can be embedded within any SVG element, including primitive shapes like circles, ellipses, and rectangles. They can also be encapsulated into groups, paths, and polygons:
<circle ...>
<animate>...</animate>
</circle>
Animations can also be defined outside an element, elsewhere in an SVG, and connected to it using an xlink attribute:
<g id="yogi">...</g>
...
<animate xlink:href="#yogi">…</animate>
Building An Animation
<animate> is just one of several animation elements in SVG. Together with an attributeName value, it enables animations based on one or more of an element’s attributes.
Most animation explanations start by moving a primitive shape, like this exciting circle:
<circle
r="50"
cx="50"
cy="50"
fill="#062326"
opacity="1"
/>
Using this attributeName property, I can define which of this circle’s attributes I want to animate, which, in this example, is its cxposition:
<circle ... >
<animate attributename="cx"></animate>
</circle>
On its own, this does precisely nothing until I define three more values. The from keyword specifies the circle’s initial position, to, its final position, and the dur-ation between those two positions:
<circle ... >
<animate
attributename="cx"
from="50"
to="500"
dur="1s">
</animate>
</circle>
If I want more precise control, I can replace from and to with a set of values separated by semicolons:
<circle ... >
<animate
attributename="cx"
values="50; 250; 500; 250;"
dur="1s">
</animate>
</circle>
Finally, I can define how many times the animation repeatsand even after what period that repeating should stop:
<circle ... >
<animate
attributename="cx"
values="50; 250; 500; 250;"
dur="1s"
repeatcount="indefinite"
repeatdur="180s">
</circle>
Most SVG elements have attributes that can be animated. This title card from 1959’s “Brainy Bear” episode shows Yogi in a crazy scientist‘s brain experiment. Yogi’s head is under the dome, and energy radiates around him.
To create the buzz around Yogi, my SVG includes three path elements, each with opacity, stroke, and stroke-width attributes, which can all be animated:
<path opacity="1" stroke="#fff" stroke-width="5" ... />
I animated each path’s opacity, changing its value from 1 to .5 and back again:
<path opacity="1" ... >
<animate
attributename="opacity"
values="1; .25; 1;"
dur="1s"
repeatcount="indefinite">
</animate>
</path>
Then, to radiate energy from Yogi, I specified when each animation should begin, using a different value for each path:
<path ... >
<animate begin="0" … >
</path>
<path ... >
<animate begin=".5s" … >
</path>
<path ... >
<animate begin="1s" … >
</path>
I’ll explain more about the begin property and how to start animations after this short commercial break.
Try this yourself:
I needed two types of transform animations to generate the effect of Yogi drifting gently downwards: translate, and rotate. I first added an animatetransform element to the group, which contains Yogi and his chute. I defined his initial vertical position — 1200 off the top of the viewBox — then translated his descent to 1000 over a 15-second duration:
<g transform="translate">
...
<animateTransform
attributeName="transform"
type="translate"
values="500,-1200; 500,1000"
dur="15s"
repeatCount="1"
/>
</g>
Yogi appears to fall from the sky, but the movement looks unrealistic. So, I added a second animatetransform element, this time with an indefinitely repeating +/- 5-degree rotation to swing Yogi from side to side during his descent:
<animateTransform
attributeName="transform"
type="rotate"
values="-5; 5; -5"
dur="14s"
repeatCount="indefinite"
additive="sum"
/>
Try this yourself:
By default, the arrow is set loose when the page loads. Blink, and you might miss it. To build some anticipation, I can begin the animation two seconds later:
<animatetransform
attributename="transform"
type="translate"
from="0 0"
to="750 0"
dur=".25s"
begin="2s"
fill="freeze"
/>
Or, I can let the viewer take the shot when they click the arrow:
<animatetransform
...
begin="click"
/>
And I can combine the click event and a delay, all with no JavaScript, just a smattering of SMIL:
<animatetransform
...
begin="click + .5s"
/>
Try this yourself by clicking the arrow:
To bring this title card to life, I needed two groups of paths: one for Yogi and the other for the dog. I translated them both off the left edge of the viewBox:
<g class="dog" transform="translate">
...
</g>
<g class="yogi" transform="translate">
...
</g>
Then, I applied an animatetransform element to both groups, which moves them back into view:
<!-- yogi -->
<animateTransform
attributeName="transform"
type="translate"
from="-1000,0"
to="0,0"
dur="2s"
fill="freeze"
/>
<!-- dog -->
<animateTransform
attributeName="transform"
type="translate"
from="-1000,0"
to="0,0"
dur=".5s"
fill="freeze"
/>
This sets up the action, but the effect feels flat, so I added another pair of animations that bounce both characters:
<!-- yogi -->
<animateTransform
attributeName="transform"
type="rotate"
values="-1,0,450; 1,0,450; -1,0,450"
dur=".25s"
repeatCount="indefinite"
/>
<!-- dog -->
<animateTransform
attributeName="transform"
type="rotate"
values="-1,0,450; 1,0,450; -1,0,450"
dur="0.5s"
repeatCount="indefinite"
/>
Animations can begin when a page loads, after a specified time, or when clicked. And by naming them, they can also synchronise with other animations.
I wanted Yogi to enter the frame first to build anticipation, with a short pause before other animations begin, synchronising to the moment he’s arrived. First, I added an ID to Yogi’s translate animation:
<animateTransform
id="yogi"
type="translate"
...
/>
Watch out: For a reason, I can’t, for the life of me, explain why Firefox won’t begin animations with an ID when the ID contains a hyphen. This isn’t smarter than the average browser, but replacing hyphens with underscores fixes the problem.
Then, I applied a begin to his rotate animation, which starts playing a half-second after the #yogi animation ends:
<animateTransform
type="rotate"
begin="yogi.end + .5s"
...
/>
I can build sophisticated sets of synchronised animations using the begin property and whether a named animation begins or ends. The bulldog chasing Yogi enters the frame two seconds after Yogi begins his entrance:
<animateTransform
id="dog"
type="translate"
begin="yogi.begin + 2s"
fill="freeze"
...
/>
One second after the dog has caught up with Yogi, a rotate transformation makes him bounce, too:
<animateTransform
type="rotate"
...
begin="dog.begin + 1s"
repeatCount="indefinite"
/>
The background rectangles whizzing past are also synchronised, this time to one second before the bulldog ends his run:
<rect ...>
<animateTransform
begin="dog.end + -1s"
/>
</rect>
Try this yourself:
In “The Runaway Bear” from 1959, Yogi must avoid a hunter turning his head into a trophy. I wanted Yogi to leap in and out of the screen by making him follow a path. I also wanted to vary the speed of his dash: speeding up as he enters and exits, and slowing down as he passes the title text.
I first added a path property, using its coordinate data to give Yogi a route to follow, and specified a two-second duration for my animation:
<g>
<animateMotion
dur="2s"
path="..."
>
</animateMotion>
</g>
Alternatively, I could add a path element, leave it visible, or prevent it from being rendered by placing it inside a defs element:
<defs>
<path id="yogi" d="..." />
</defs>
I can then reference that by using a mpath element inside my animateMotion:
<animateMotion
...
<mpath href="#yogi" />
</animateMotion>
I experimented with several paths before settling on the one that delivered the movement shape I was looking for:
One was too bouncy, one was too flat, but the third motion path was just right. Almost, as I also wanted to vary the speed of Yogi’s dash: speeding him up as he enters and exits and slowing him down as he passes the title text.
The keyPoints property enabled me to specify points along the motion path and then adjust the duration Yogi spends between them. To keep things simple, I defined five points between 0 and 1:
<animateMotion
...
keyPoints="0; .35; .5; .65; 1;"
>
</animateMotion>
Then I added the same number of keyTimes values, separated by semicolons, to control the pacing of this animation:
<animateMotion
...
keyTimes="0; .1; .5; .95; 1;"
>
</animateMotion>
Now, Yogi rushes through the first three keyPoints, slows down as he passes the title text, then speeds up again as he exits the viewBox.
Try this yourself:
See the Pen Runaway Bear SVG animationby Andy Clarke.
SMIL’s Not Dead, Baby. SMIL’s Not Dead
With their ability to control transformations, animate complex motion paths, and synchronise multiple animations, SMIL animations in SVG are still powerful tools. They can bring design to life without needing a framework or relying on JavaScript. It’s compact, which makes it great for small SVG effects.
SMIL includes the begin attribute, which makes chaining animations far more intuitive than with CSS. Plus, SMIL lives inside the SVG file, making it perfect for animations that travel with an asset. So, while SMIL is not modern by today’s standards and may be a little bit niche, it can still be magical.
Don’t let the misconception that SMIL is “dead” stop you from using this fantastic tool.
Google reversed its decision to deprecate SMIL almost a decade ago, so it remains a terrific choice for designers and developers who want simple, semantic ways to add animations to their designs.
#smashing #animations #part #3smilsnotdeadbaby #smilsnotdead
Smashing Animations Part 3: SMIL’s Not Dead Baby, SMIL’s Not Dead
The SMIL specification was introduced by the W3C in 1998 for synchronizing multimedia. This was long before CSS animations or JavaScript-based animation libraries were available. It was built into SVG 1.1, which is why we can still use it there today.
Now, you might’ve heard that SMIL is dead. However, it’s alive and well since Google reversed a decision to deprecate the technology almost a decade ago. It remains a terrific choice for designers and developers who want simple, semantic ways to add animations to their designs.
Tip: There’s now a website where you can see all my Toon Titles.
Mike loves ’90s animation — especially Disney’s) Duck Tales). Unsurprisingly, my taste in cartoons stretches back a little further to Hanna-Barbera shows like Dastardly and Muttley in Their Flying Machines, Scooby-Doo, The Perils of Penelope Pitstop, Wacky Races, and, of course, The Yogi Bear Show. So, to explain how this era of animation relates to SVG, I’ll be adding SMIL animations in SVG to title cards from some classic Yogi Bear cartoons.
Fundamentally, animation changes how an element looks and where it appears over time using a few basic techniques. That might be simply shifting an element up or down, left or right, to create the appearance of motion, like Yogi Bear moving across the screen.
Rotating objects around a fixed point can create everything, from simple spinning effects to natural-looking movements of totally normal things, like a bear under a parachute falling from the sky.
Scaling makes an element grow, shrink, or stretch, which can add drama, create perspective, or simulate depth.
Changing colour and transitioning opacity can add atmosphere, create a mood, and enhance visual storytelling. Just these basic principles can create animations that attract attention and improve someone’s experience using a design.
These results are all achievable using CSS animations, but some SVG properties can’t be animated using CSS. Luckily, we can do more — and have much more fun — using SMIL animations in SVG. We can combine complex animations, move objects along paths, and control when they start, stop, and everything in between.
Animations can be embedded within any SVG element, including primitive shapes like circles, ellipses, and rectangles. They can also be encapsulated into groups, paths, and polygons:
<circle ...>
<animate>...</animate>
</circle>
Animations can also be defined outside an element, elsewhere in an SVG, and connected to it using an xlink attribute:
<g id="yogi">...</g>
...
<animate xlink:href="#yogi">…</animate>
Building An Animation
<animate> is just one of several animation elements in SVG. Together with an attributeName value, it enables animations based on one or more of an element’s attributes.
Most animation explanations start by moving a primitive shape, like this exciting circle:
<circle
r="50"
cx="50"
cy="50"
fill="#062326"
opacity="1"
/>
Using this attributeName property, I can define which of this circle’s attributes I want to animate, which, in this example, is its cxposition:
<circle ... >
<animate attributename="cx"></animate>
</circle>
On its own, this does precisely nothing until I define three more values. The from keyword specifies the circle’s initial position, to, its final position, and the dur-ation between those two positions:
<circle ... >
<animate
attributename="cx"
from="50"
to="500"
dur="1s">
</animate>
</circle>
If I want more precise control, I can replace from and to with a set of values separated by semicolons:
<circle ... >
<animate
attributename="cx"
values="50; 250; 500; 250;"
dur="1s">
</animate>
</circle>
Finally, I can define how many times the animation repeatsand even after what period that repeating should stop:
<circle ... >
<animate
attributename="cx"
values="50; 250; 500; 250;"
dur="1s"
repeatcount="indefinite"
repeatdur="180s">
</circle>
Most SVG elements have attributes that can be animated. This title card from 1959’s “Brainy Bear” episode shows Yogi in a crazy scientist‘s brain experiment. Yogi’s head is under the dome, and energy radiates around him.
To create the buzz around Yogi, my SVG includes three path elements, each with opacity, stroke, and stroke-width attributes, which can all be animated:
<path opacity="1" stroke="#fff" stroke-width="5" ... />
I animated each path’s opacity, changing its value from 1 to .5 and back again:
<path opacity="1" ... >
<animate
attributename="opacity"
values="1; .25; 1;"
dur="1s"
repeatcount="indefinite">
</animate>
</path>
Then, to radiate energy from Yogi, I specified when each animation should begin, using a different value for each path:
<path ... >
<animate begin="0" … >
</path>
<path ... >
<animate begin=".5s" … >
</path>
<path ... >
<animate begin="1s" … >
</path>
I’ll explain more about the begin property and how to start animations after this short commercial break.
Try this yourself:
I needed two types of transform animations to generate the effect of Yogi drifting gently downwards: translate, and rotate. I first added an animatetransform element to the group, which contains Yogi and his chute. I defined his initial vertical position — 1200 off the top of the viewBox — then translated his descent to 1000 over a 15-second duration:
<g transform="translate">
...
<animateTransform
attributeName="transform"
type="translate"
values="500,-1200; 500,1000"
dur="15s"
repeatCount="1"
/>
</g>
Yogi appears to fall from the sky, but the movement looks unrealistic. So, I added a second animatetransform element, this time with an indefinitely repeating +/- 5-degree rotation to swing Yogi from side to side during his descent:
<animateTransform
attributeName="transform"
type="rotate"
values="-5; 5; -5"
dur="14s"
repeatCount="indefinite"
additive="sum"
/>
Try this yourself:
By default, the arrow is set loose when the page loads. Blink, and you might miss it. To build some anticipation, I can begin the animation two seconds later:
<animatetransform
attributename="transform"
type="translate"
from="0 0"
to="750 0"
dur=".25s"
begin="2s"
fill="freeze"
/>
Or, I can let the viewer take the shot when they click the arrow:
<animatetransform
...
begin="click"
/>
And I can combine the click event and a delay, all with no JavaScript, just a smattering of SMIL:
<animatetransform
...
begin="click + .5s"
/>
Try this yourself by clicking the arrow:
To bring this title card to life, I needed two groups of paths: one for Yogi and the other for the dog. I translated them both off the left edge of the viewBox:
<g class="dog" transform="translate">
...
</g>
<g class="yogi" transform="translate">
...
</g>
Then, I applied an animatetransform element to both groups, which moves them back into view:
<!-- yogi -->
<animateTransform
attributeName="transform"
type="translate"
from="-1000,0"
to="0,0"
dur="2s"
fill="freeze"
/>
<!-- dog -->
<animateTransform
attributeName="transform"
type="translate"
from="-1000,0"
to="0,0"
dur=".5s"
fill="freeze"
/>
This sets up the action, but the effect feels flat, so I added another pair of animations that bounce both characters:
<!-- yogi -->
<animateTransform
attributeName="transform"
type="rotate"
values="-1,0,450; 1,0,450; -1,0,450"
dur=".25s"
repeatCount="indefinite"
/>
<!-- dog -->
<animateTransform
attributeName="transform"
type="rotate"
values="-1,0,450; 1,0,450; -1,0,450"
dur="0.5s"
repeatCount="indefinite"
/>
Animations can begin when a page loads, after a specified time, or when clicked. And by naming them, they can also synchronise with other animations.
I wanted Yogi to enter the frame first to build anticipation, with a short pause before other animations begin, synchronising to the moment he’s arrived. First, I added an ID to Yogi’s translate animation:
<animateTransform
id="yogi"
type="translate"
...
/>
Watch out: For a reason, I can’t, for the life of me, explain why Firefox won’t begin animations with an ID when the ID contains a hyphen. This isn’t smarter than the average browser, but replacing hyphens with underscores fixes the problem.
Then, I applied a begin to his rotate animation, which starts playing a half-second after the #yogi animation ends:
<animateTransform
type="rotate"
begin="yogi.end + .5s"
...
/>
I can build sophisticated sets of synchronised animations using the begin property and whether a named animation begins or ends. The bulldog chasing Yogi enters the frame two seconds after Yogi begins his entrance:
<animateTransform
id="dog"
type="translate"
begin="yogi.begin + 2s"
fill="freeze"
...
/>
One second after the dog has caught up with Yogi, a rotate transformation makes him bounce, too:
<animateTransform
type="rotate"
...
begin="dog.begin + 1s"
repeatCount="indefinite"
/>
The background rectangles whizzing past are also synchronised, this time to one second before the bulldog ends his run:
<rect ...>
<animateTransform
begin="dog.end + -1s"
/>
</rect>
Try this yourself:
In “The Runaway Bear” from 1959, Yogi must avoid a hunter turning his head into a trophy. I wanted Yogi to leap in and out of the screen by making him follow a path. I also wanted to vary the speed of his dash: speeding up as he enters and exits, and slowing down as he passes the title text.
I first added a path property, using its coordinate data to give Yogi a route to follow, and specified a two-second duration for my animation:
<g>
<animateMotion
dur="2s"
path="..."
>
</animateMotion>
</g>
Alternatively, I could add a path element, leave it visible, or prevent it from being rendered by placing it inside a defs element:
<defs>
<path id="yogi" d="..." />
</defs>
I can then reference that by using a mpath element inside my animateMotion:
<animateMotion
...
<mpath href="#yogi" />
</animateMotion>
I experimented with several paths before settling on the one that delivered the movement shape I was looking for:
One was too bouncy, one was too flat, but the third motion path was just right. Almost, as I also wanted to vary the speed of Yogi’s dash: speeding him up as he enters and exits and slowing him down as he passes the title text.
The keyPoints property enabled me to specify points along the motion path and then adjust the duration Yogi spends between them. To keep things simple, I defined five points between 0 and 1:
<animateMotion
...
keyPoints="0; .35; .5; .65; 1;"
>
</animateMotion>
Then I added the same number of keyTimes values, separated by semicolons, to control the pacing of this animation:
<animateMotion
...
keyTimes="0; .1; .5; .95; 1;"
>
</animateMotion>
Now, Yogi rushes through the first three keyPoints, slows down as he passes the title text, then speeds up again as he exits the viewBox.
Try this yourself:
See the Pen Runaway Bear SVG animationby Andy Clarke.
SMIL’s Not Dead, Baby. SMIL’s Not Dead
With their ability to control transformations, animate complex motion paths, and synchronise multiple animations, SMIL animations in SVG are still powerful tools. They can bring design to life without needing a framework or relying on JavaScript. It’s compact, which makes it great for small SVG effects.
SMIL includes the begin attribute, which makes chaining animations far more intuitive than with CSS. Plus, SMIL lives inside the SVG file, making it perfect for animations that travel with an asset. So, while SMIL is not modern by today’s standards and may be a little bit niche, it can still be magical.
Don’t let the misconception that SMIL is “dead” stop you from using this fantastic tool.
Google reversed its decision to deprecate SMIL almost a decade ago, so it remains a terrific choice for designers and developers who want simple, semantic ways to add animations to their designs.
#smashing #animations #part #3smilsnotdeadbaby #smilsnotdead
·86 Views