As an entertainment medium, the web requires a judicious use of special effects to catch and hold interest. In contrast to other media formats, however, the web is limited by bandwidth. If we can find ways to make interesting effects with less data sent over the wire, we all win.
In this article, I’m going to talk about techniques to do more with some simple SVG tricks. In the interest of brevity, I shall assume readers have a rudimentary knowledge of SVG, so I will not explain the more basic concepts.
At the same time, to keep the code more easily understandable, I’ll avoid various optimizations so that I don’t have to explain them. This means the code will at times be more verbose than necessary, but recognize the verbosity is in the service of clarity.
The following snippet of SVG code represents a circle:
<circle cx="50" cy="50" r="25" fill="#ff0000" />
As do these:
<circle cx="50" cy="50" r="25" fill="#ffff00" /> <circle cx="50" cy="50" r="25" fill="#ffffff" />
If you have the first two circles in an SVG, you will see a single yellow circle. If you have all three, you should see nothing — assuming the SVG they are in is white.
See the Pen
Layered Circles by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
The reason for this is SVG’s z-indexing rules, which dictate that when any two graphical elements occupy the same space, the one represented later in the XML tree that the SVG is described by will be given a higher z-index
. The white circle is at the same position as the yellow and covers it precisely.
The r
attribute on each circle represents its radius. Thus, if you want to have layered circles where you can see the circles underneath, you might do so by increasing the radius, like so:
See the Pen
Layered Circles Visible by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
If you did not have the white circle, it would look like you had a yellow circle with a thick red border or stroke. The same principle applies to other graphical elements in SVG.
Let’s suppose we put the following rectangle in between the white and yellow circle.
<rect x="25" y="25" width="50" height="50" fill="#ff00ff" />
Notice the x
and y
are half the cx
and cy
of the circle — because circles are drawn from the center out, and rectangles are drawn from the top left. It will look like this:
See the Pen
Layered Circles And Rects Visible by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
And finally, I will put another rectangle in between our previous rectangle and the white circle and rotate it to make a simple star shape:
<rect x="25" y="25" width="50" height="50" fill="#ff00ff" transform = "rotate(45 50 50)"/>
The 50
values represent the center of the rectangle, which is, of course, the same value as the cx
and cy
of our circle.
See the Pen
Layered Circles And Rects 2 by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
>
I think at this point we have enough little areas to play with that we can see about making some interesting effects with animation.
animateTransform
One of the easiest ways to animate things in SVG is to use animateTransform
, which animates a transformation attribute on its target element. In other words, if I put an animateTransform
element as a child of one of these rectangles, I can animate the transform attribute, which we used in our earlier example to rotate our last rect
.
If we add the following animateTransform
as the child of the last rectangle…
<animateTransform attributeName="transform" type="rotate" from="0 50 50" to="360 50 50" dur="10s" repeatCount="indefinite" />
…we will cause that rectangle to rotate a full 360 degrees every 10 seconds indefinitely.
The first number of the from
attribute is from how many degrees it should be rotated at the start of the animation; the first number of the to
is how many degrees it should be rotated at the end of the animation. And if we are doing this, we can remove the original transform attribute on the rectangle, as it is rendered redundantly. Like so:
See the Pen
Layered Circles And Rects 2 Animated by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
animate
animate
allows you to animate less complicated attributes than the transform attribute, but in the same manner.
As an example, let’s add the following animate
element as the child of our rectangle that has the animateTransform
:
<animate attributeName="fill" values="#ff0000; #ffff00; #ff00ff;" dur="10s" repeatCount="indefinite" />
Visible here:
See the Pen
Layered Circles And Rects 2 Animated 2 by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
As an example of how the other properties of the animation — like its duration and the number of times to repeat it — can create interesting effects, take a look at this layering of circles.
Each circle has a different duration of animating the fill, the number of times it repeats is set so that they should stop at different times — all except the inner circle, the last in the XML tree, which should have its fill animated forever.
See the Pen
Layered Circles animate fills in sequence by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
As for how you can animate other SVG properties, the following example animates the cx
property of a number of layered circles. The duration is off by a bit for each one, and the starting time is such that the bottom layer starts first, the top layer starts last, and they all finish one after the other.
The fill
property is set to freeze
on the animation, which means the attribute will end up with the value that ends the animation (in this case, 250
).
See the Pen
Layered Circles animated cx in sequence by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
One last thing to note about these animations is that transparent is a color — this fact will be of use in the next section.
Look at the following animation:
See the Pen
Layered Circles animated cx with stop points and images by Bryan Rasmussen (@bryanrasmussen)
on CodePen.
What’s happening here is that there are 18 circles in the SVG. Twelve of the circles are placed along the length of the SVG in pairs — that is to say, there are two circles at cx="100"
on the x radius, two circles at cx="200"
, and so forth. Here is the code for the first pair of circles:
<circle cx="100" cy="50" r="30" fill="url(#image1)"></circle> <circle cx="100" cy="50" r="30" fill="#ffffff"> <animate attributeName="fill" values="#ffffff;transparent; " begin="6.1s" dur="0.1s" fill="freeze" repeatCount="1" /> </circle>
Because these two circles sit in the same place, the one that comes later in the markup tree has the higher z-index. So the circle with a fill color of white sits on top of a circle that is filled by an image.
But that white-colored circle has an animation that makes it transparent, meaning you can see the image in the circle underneath when the animation is finished.
Finally, there are six circles that start off at the same location — cx="50"
, cy="50"
— and are animated along their cx
. Each one of these circles stops somewhere, covering one of the white circles that, in turn, cover the circle with an image in it.
The white circle animations start after the six circles are done moving to their respective cx
positions. Then, the six circles have an animation on their fill to move from either yellow or red to transparent. Of course, when they are done animating, the white circles are already done animating; therefore, we see the circles with images in them after the fill color of the top image becomes transparent.
In conclusion, with SVG’s z-indexing and properly timed animations, it is pretty simple to construct advanced effects through simple markup patterns that catch the user’s attention.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.