Welcome to the second tutorial in a series of tutorials all about SVG’s! In this second tutorial we will cover how to animate the simple SVG shapes. The types of animation include:
If you are new to the world of SVG it’s best to go through my SVG basics tutorial before this one. Otherwise dive right in!
Learn how to animate a colour transition from blue to green and back:
@keyframes colour_change { from { fill: blue; } to { fill: green; } } circle { animation: colour_change 2s infinite alternate; }
CSS Animations
In this example we are using:
These are all standard CSS abilities.
<svg width="300" height="200" xmlns="http://www.w3.org/2000/svg">
<style>
@keyframes colour_change {
from { fill: blue; }
to { fill: green; }
}
circle {
animation: colour_change 2s infinite alternate;
}
</style>
<circle cx="100" cy="100" r="80" fill="blue" />
</svg>
Learn how to animate the transformation from left to right and back again:
@keyframes move { from { transform: translate(50px); } to { transform: translate(300px); } } circle { animation: move 1s linear infinite alternate; }
CSS Transforms
This example shows how you can use CSS transforms to manipulate SVG elements. It’s possible to use a wide range of CSS transforms:
Translate
Move an element based on x/y coordinates:
transform: translate(50px, 50px)
Rotate
Rotates an element:
transform: rotate(45deg)
Skew
2D Skew an element in either the x and/or y direction:
transform: skew(15deg, 15deg)
Scale
Scale an element in the x and/or y direction:
transform: scale(0.5, 1.5)
It is also possible to apply transforms in 3D space.
<svg width="450" height="200" xmlns="http://www.w3.org/2000/svg">
<style>
@keyframes move {
from { transform: translate(50px); }
to { transform: translate(300px); }
}
circle {
animation: move 1s linear infinite alternate;
}
</style>
<circle cx="50" cy="100" r="80" fill="blue" />
</svg>
Learn how to animate the transformation from left to right along an arc:
@keyframes move { 0% { transform: rotate(0deg); fill: red;} 50% { fill: yellow;} 100% { transform: rotate(220deg); fill: red;} } .sun { transform-origin: 400px 400px; animation: move 4s ease-in-out infinite; }
@keyframes
Keyframes are used to define the animation steps. The steps can be defined as either “from”, “to” or more granularly with percentage values.
transform-origin
This allows us to set the point of rotation. In this example it is set to the bottom center of the image.
ease-in-out
Here we define the transition-timing-function which is the speed curve of the transition effect. In this example the animation starts slow, speeds up and then ends slow.
<svg width="800" height="400" xmlns="http://www.w3.org/2000/svg">
<style>
@keyframes move {
0% { transform: rotate(0deg); fill: red;}
50% { fill: yellow;}
100% { transform: rotate(220deg); fill: red;}
}
.sun {
transform-origin: 400px 400px;
animation: move 4s ease-in-out infinite;
}
</style>
<rect x="0" y="0" width="800" height="400" fill="lightblue"/>
<circle cx="100" cy="500" r="100" class="sun" />
</svg>
Learn how to animate the rise, fall and squash of a bouncing ball:
@keyframes bounce { 40% { transform: translateY(200px) scale(1, 1); } 50% { transform: translateY(190px) scale(1.1, 0.9); } 60% { transform: translateY(200px) scale(1, 1); } } .ball { transform-origin: 50% 50%; animation: bounce 1s infinite; }
Bounce: @keyframes
Steps 0% and 100% are omitted in this example so the defaults values are automatically used.
Ball: transform-origin
The transform-origin is set to the center of the ball. This allows our squash (scale) transformation to work as required.
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<style>
@keyframes bounce {
40% { transform: translateY(200px) scale(1, 1); }
50% { transform: translateY(190px) scale(1.1, 0.9); }
60% { transform: translateY(200px) scale(1, 1); }
}
.ball {
transform-origin: 50% 50%;
animation: bounce 1s infinite;
}
</style>
<rect x="0" y="0" width="400" height="400" fill="skyblue"/>
<rect x="0" y="300" width="400" height="100" fill="#44cf6c"/>
<circle class="ball" cx="200" cy="50" r="50" fill="#db5461"/>
</svg>
Learn how to add depth to the Bouncing Ball animation:
@keyframes bounce { 40% { transform: translateY(200px) scale(1, 1); } 50% { transform: translateY(190px) scale(1.1, 0.9); } 60% { transform: translateY(200px) scale(1, 1); } } .ball { transform-origin: 50% 50%; animation: bounce 1s infinite; }
Shadow: @keyframes
Shrink the shadow using scaling as the ball rises.
Shadow: transform-origin
Set the shadows transform-origin to the center of the ellipse so that it scales around its center
Ground:
Raise the ground slightly to give the impression of depth
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg">
<style>
@keyframes bounce {
40% { transform: translateY(200px) scale(1, 1); }
50% { transform: translateY(190px) scale(1.1, 0.9); }
60% { transform: translateY(200px) scale(1, 1); }
}
@keyframes shadow {
0% { transform: scale(0.5) ; }
50% { transform: scale(1) ; }
100% { transform: scale(0.5) ; }
}
.ball {
transform-origin: 50% 50%;
animation: bounce 1s infinite;
}
.shadow{
transform-origin: 50% 300px;
animation: shadow 1s infinite;
}
</style>
<rect x="0" y="0" width="400" height="400" fill="skyblue"/>
<rect x="0" width="400" height="125" y="275" fill="#44cf6c"/>
<ellipse class="shadow" cx="200" rx="50" cy="300" ry="15" />
<circle class="ball" cx="200" cy="50" r="50" fill="#db5461" />
</svg>
Learn how to animate path elements and strokes:
.eyes { stroke-dasharray: 38; stroke-dashoffset: 38; }
<path id="mouth" d="M160,250 C175,250 225,250 240,250" stroke-linecap="round" stroke="black" stroke-width="7" fill="none" />
stroke-dasharray
The stroke dash array converts a solid stroke line to a dash: “-----”. The value is the length of each dash line in pixels. In our example we can only see one dash line
stroke-dashoffset
The stroke dash offset determines the start point of the first dash line. By animating the offset we can make the half moon eyes appear to move!
**Note:** The circumference of the eye is ~76px which is why we use 38px for the stroke (half the circumference)
The path element can be used to define any shape. The “d” element defines the path to be drawn. There are six path commands the “d” element understands:
Note: Uppercase letters use absolute coordinates whilst lowercase letters use relative coordinates
<svg width="400" height="400" version="1.1" xmlns="http://www.w3.org/2000/svg">
<style>
@keyframes smile {
0% {
d: path("M160,250 C175,240 225,240 240,250");
}
20% {
d: path("M160,250 C175,240 225,240 240,250");
}
80% {
d: path("M160,250 C175,285 225,285 240,250");
}
100% {
d: path("M160,250 C175,285 225,285 240,250");
}
}
@keyframes eyes-ani {
0% {
stroke-dashoffset: 0;
}
20% {
stroke-dashoffset: 0;
}
80% {
stroke-dashoffset: 38;
}
100% {
stroke-dashoffset: 38;
}
}
#mouth {
animation: smile 3s infinite alternate;
}
.eyes {
animation: eyes-ani 3s infinite alternate;
fill: none;
stroke: black;
stroke-width: 7;
stroke-dasharray: 38;
stroke-dashoffset: 38;
}
</style>
<rect x="0" y="0" width="400" height="400" fill="skyblue" />
<circle stroke="black" stroke-width="7" fill="yellow" cx="200" cy="200" r="100" />
<circle class="eyes" r="12" cx="160" cy="175" />
<circle class="eyes" r="12" cx="240" cy="175" />
<path id="mouth" d="M160,250 C175,250 225,250 240,250" stroke-linecap="round" stroke="black" stroke-width="7" fill="none" />
</svg>
Finally! You’ve learnt something interesting! Go forth and animate!
In the next lesson we will look at how to integrate these animations into a website.
I hope this post was helpful. Please get in touch with any feedback you have: