Let’s make stuff with SVG shaaaall we. But no! you say. SVG is weird and complicated. Well, true, but it’s basically a superpower once we start to understand all the things it can do.
bouncy trouncy pouncy flouncy, fun fun fun fun fun!
First off, let’s go grab an SVG version of a DVD logo to animate through. Wikipedia has our back with this bad boy: https://commons.wikimedia.org/wiki/File:DVD_logo.svg, but there’s some weirdness…
When we inspect (right-click > Inspect) on the logo itself, we see it’s comprised of 2 elements with a bunch of scary-looking numbers and whatnot. So let’s copy the big ol’ values of the d property for both of these path elements into this handy SVG path editor tool and see what it looks like.
Now we can mess around with how it looks if we want. I went ahead and scaled it down and rounded it to 1 decimal to make it look a little better inside my 1000 x 1000 viewBox: viewBox="0 0 1000 1000".
I like simple base 10 viewBoxes. Don’t judge me!
Here’s the combined path d value I ended up using:
M 91.2 12.7 C 91.2 12.7 80.2 26.3 80.8 27.1 C 81.6 26.3 76.8 12.5 76.8 12.5 S 75.8 9.7 72.8 0.1 H 13.8 L 11.8 8.9 H 30.8 C 40.8 8.9 46.8 13.1 45.2 20.3 C 43.4 28.3 34.8 31.7 25.4 31.7 H 22 L 26.4 12.3 H 11 L 4.4 40.5 H 26.4 C 42.8 40.5 58.6 31.7 61.4 20.3 C 61.8 18.3 61.8 12.9 60.6 9.9 C 60.4 9.5 60.2 8.9 60.6 8.9 C 60.8 8.9 61 9.1 61 9.1 L 75.2 49.9 L 110.8 8.9 H 129.4 C 139.4 8.9 145.4 13.1 143.8 20.3 C 142 28.3 133.2 31.7 124 31.7 H 120.4 L 124.8 12.5 H 109.4 L 102.8 40.7 H 124.8 C 141.2 40.7 157 31.9 159.6 20.5 C 162.2 9.1 150.8 0.3 134 0.3 H 101.2 C 92.8 10.7 91.2 12.7 91.2 12.7 L 91.2 12.7 Z M 75.6 50.3 C 33.8 50.3 0 55.3 0 61.3 C 0 67.3 33.8 72.3 75.6 72.3 C 117.4 72.3 151.2 67.5 151.2 61.3 C 151.2 55.3 117.4 50.3 75.6 50.3 Z M 72.8 65.1 C 63.2 65.1 55.6 63.5 55.6 61.5 C 55.6 59.5 63.2 57.9 72.8 57.9 C 82.4 57.9 90 59.5 90 61.5 C 90 63.5 82.4 65.1 72.8 65.1 Z
Now we need to make use of an SVG trick where we can animate the x and y position of an inner SVG inside of an outer one based on percentages.
<svg class="outerSVG" xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" viewBox="0 0 1000 1000">
<rect id="tvBackground" height="100%" width="100%" fill="#222" rx="10" />
<svg id="innerSVG" height="100%" width="100%" fill="#0ff">
<path id="dvdLogo" fill="inherit" d="MY-SCALED-DOWN-PATH" />
<!-- animation elements-->
.........
This will animate the inner SVG relative to the outer one. Then we stagger the timing of the x and y animations so the inner SVG hits one edge first:
<animate attributeName="x" dur="9" values="0%;84%;0%" repeatCount="indefinite" />
<animate attributeName="y" dur="10" values="0%;92%;0%" repeatCount="indefinite" />
I dialed in the above edge values so that there’s no overflow. So for the y value, instead of animating the DVD logo from 0% to 100% and then back to 0%, we animate from 0% > 92% > 0% so that the logo doesn’t briefly disappear off the bottom of the SVG when it reaches the bottom edge.
Change color on bounce
On to the color changing. We could always use JavaScript, but let’s not do that! We’re gonna keep everything nice and compact inside of 1 SVG file.
To achieve this, we’re gonna need to get a little (more) hackey. Since the bouncing happens whenever we hit the edge of the X or Y axis, we can time a color change animation to the repeatEvent of the x and y animations.
But this will only change the color 2 times; when we hit the top and the left. So we need to add 2 empty animation events that are timed to the middle of the initial x and y animations. These will trigger 2 additional color changes linked to their repeatEvents so that the color changes when we hit each wall.
<!-- empty animations for triggering color changes -->
<animate id="xx" begin="-4.5s" repeatCount="indefinite" dur="9s" />
<animate id="yy" begin="-5s" repeatCount="indefinite" dur="10s" />
All of the animations together will look like this:
<animate id="xAnim" attributeName="x" dur="9" values="84%;0%;84%" repeatCount="indefinite" />
<animate id="yAnim" attributeName="y" dur="10" values="0%;92%;0%" repeatCount="indefinite" />
<animate attributeName="fill" values="#ff0" begin="xAnim.repeatEvent" repeatCount="indefinite" dur="0s" />
<animate attributeName="fill" values="#0ff" begin="yAnim.repeatEvent" repeatCount="indefinite" dur="0s" />
<animate attributeName="fill" values="#00f" begin="xx.repeatEvent" repeatCount="indefinite" dur="0s" />
<animate attributeName="fill" values="#0f0" begin="yy.repeatEvent" repeatCount="indefinite" dur="0s" />
<!-- empty animations for triggering color changes -->
<animate id="xx" begin="-4.5s" repeatCount="indefinite" dur="9s" />
<animate id="yy" begin="-5s" repeatCount="indefinite" dur="10s" />
So our final SVG will look something like this:
<svg class="svg" xmlns="[http://www.w3.org/2000/svg](http://www.w3.org/2000/svg)" viewBox="0 0 1000 1000">
<rect height="100%" width="100%" fill="#222" rx="10" />
<svg id="dvd" height="100%" width="100%" fill="#0ff">
<path fill="inherit" d="M 91.2 12.7 C 91.2 12.7 80.2 26.3 80.8 27.1 C 81.6 26.3 76.8 12.5 76.8 12.5 S 75.8 9.7 72.8 0.1 H 13.8 L 11.8 8.9 H 30.8 C 40.8 8.9 46.8 13.1 45.2 20.3 C 43.4 28.3 34.8 31.7 25.4 31.7 H 22 L 26.4 12.3 H 11 L 4.4 40.5 H 26.4 C 42.8 40.5 58.6 31.7 61.4 20.3 C 61.8 18.3 61.8 12.9 60.6 9.9 C 60.4 9.5 60.2 8.9 60.6 8.9 C 60.8 8.9 61 9.1 61 9.1 L 75.2 49.9 L 110.8 8.9 H 129.4 C 139.4 8.9 145.4 13.1 143.8 20.3 C 142 28.3 133.2 31.7 124 31.7 H 120.4 L 124.8 12.5 H 109.4 L 102.8 40.7 H 124.8 C 141.2 40.7 157 31.9 159.6 20.5 C 162.2 9.1 150.8 0.3 134 0.3 H 101.2 C 92.8 10.7 91.2 12.7 91.2 12.7 L 91.2 12.7 Z M 75.6 50.3 C 33.8 50.3 0 55.3 0 61.3 C 0 67.3 33.8 72.3 75.6 72.3 C 117.4 72.3 151.2 67.5 151.2 61.3 C 151.2 55.3 117.4 50.3 75.6 50.3 Z M 72.8 65.1 C 63.2 65.1 55.6 63.5 55.6 61.5 C 55.6 59.5 63.2 57.9 72.8 57.9 C 82.4 57.9 90 59.5 90 61.5 C 90 63.5 82.4 65.1 72.8 65.1 Z" />
<animate id="xAnim" attributeName="x" dur="9" values="0%;84%;0%" repeatCount="indefinite" />
<animate id="yAnim" attributeName="y" dur="10" values="0%;92%;0%" repeatCount="indefinite" />
<animate attributeName="fill" values="#ff0" begin="xAnim.repeatEvent" repeatCount="indefinite" dur="0s" />
<animate attributeName="fill" values="#0ff" begin="yAnim.repeatEvent" repeatCount="indefinite" dur="0s" />
<animate attributeName="fill" values="#00f" begin="xx.repeatEvent" repeatCount="indefinite" dur="0s" />
<animate attributeName="fill" values="#0f0" begin="yy.repeatEvent" repeatCount="indefinite" dur="0s" />
<!-- empty animations for triggering color changes -->
<animate id="xx" begin="-4.5s" repeatCount="indefinite" dur="9s" />
<animate id="yy" begin="-5s" repeatCount="indefinite" dur="10s" />
</svg>
</svg>
Here’s a working example on CodePen.
So that’s it. A bouncing DVD menu with just SVG and no external libraries or nothin’. Pretty neat, huh?
Top comments (0)