shared this story
View demo Download source
Today we’re going to create an animated SVG drum kit that can be played by clicking, tapping or using your keyboard, and that can also be programmed to play by itself! We’ll be making use of GreenSock’s TweenMax animation library, jQuery and the <audio> element.
Creating the SVG
Open your vector editing software of choice (I used Adobe Illustrator but there are many alternatives to choose from, such as Affinity Designer, Sketch or Inkscape) and get drawing! I find it helpful to have a few photos of what I’m trying to draw dotted around my artboard for reference. Keeping the style flat and fairly simple will make life easier, both in terms of drawing and animation, and less powerful devices will thank you for having less stuff to render. In this style a drum kit is actually a fairly simple set of (mostly) rectangular objects. While drawing any SVG that you intend to animate there are a couple of things to keep in mind:
<g> is Key
“The g element is a container used to group other SVG elements. Transformations applied to the g element are performed on all of its child elements, and any of its attributes are inherited by its child elements.”
The key part of this for us is “Transformations applied to the g element are performed on all of its child elements” this will come in very handy when animating our SVG, e.g. instead of applying animations to each individual component of the snare drum, we can simply group the elements we want to animate and apply a single animation to that group. Well organised, well named groups will make manipulating the SVG much easier later on!
If your drawing app has an option to do so, enable XML id names (in Illustrator Preferences > Units > Identify Objects By: > XML ID) this allows you to edit/see the actual id attribute of the elements and groups that we’ll use to target them.
There are two main sets of elements that we need to group together:
1. Tap/Click Targets
We want to be able to trigger our animations and sounds based on their respective drum being tapped/clicked, so we need to group the tap/click “target” elements together. For example, group the entire snare drum, including the stand, so any part the user touches will trigger the animation/sound.
2. Animation Targets
Group elements together that we want to animate. For example, group the snare drum; when the snare drum animation is triggered we only want to animate the drum, not the stand as well.
Draw it all, then reveal
“I find it’s useful to draw everything then reveal parts when needed.”
We want to be able to play the drums with a keyboard, so some indication of which keys trigger the drums would be useful. Choose the keys you want to “play” each drum with and add some indication to your SVG. Group these together so we can hide/show these later.
Exporting the SVG
Save your file with all your groups visible as a .svg and open it up in a text editor.
We can put this straight into our HTML document. However, I recommend optimising the SVG for the Web first. There are plenty of tools available to do this, with SVGOMG probably being one of the simplest to use.
See Drums, Hear Drums
We don’t just want our drums to look like they’re being played; we want to hear them, too! We’ll need separate audio files for each of our drum sounds. I exported the audio used in the demo from Logic, using some of the packaged royalty-free loops. However, there are many other resources for getting free drum samples on the Web, such as 99 Sounds and Bedroom Producers Blog.
We can include our audio files using the <audio> element. Then we set the src attribute on either the <audio> element or a child <source> element where we also need to include its type (the audio file format).
We give the audio elements IDs so that we can target them when they need to be played.
(Pre)Load those Beats
By adding the attribute preload="auto" we can tell the browser “the user needs this, make sure it gets downloaded”. That’s how it works in some browsers anyway. Other browsers (particularly those on mobile devices) actually ignore this, which can lead to some odd behavior, but we’ll come back to this later.
We’ve got a lot to do before we can play our drums, but each drum part can be broken down into three steps:
Trigger these on user interaction.
Let’s start by storing the DOM elements we need as variables. E.g., for the snare we want the snare audio, and snare drum, both bits we want to animate and the parts that will trigger the animation and audio.
Playing our audio is actually pretty straightforward: we simply use the .play() method on the audio element we’d like to play.
That’s it! Well almost… This works great, but if we call the method again while the audio is already playing, nothing will happen. We want the sound to be triggered from the beginning of the audio file every time a drum is triggered. So we need to set where the audio start position is every time it’s being triggered.
Create a new timeline
Tween a property (or lots of properties) of the element
Tween back to the original state
We’re simply trying to emulate something close to how we “expect” the drum to move when it’s hit. Sometimes it pays to exaggerate the amount of movement to get the desired effect. This is partly trial and error but fortunately there are lots of great examples of GreenSock in action you can check out for inspiration.Also, following people like Chris Gannon is a great way of seeing what GreenSock can do.
Finally, easing is one of the most useful tools GreenSock provides to give your animation the right “feel”. GreenSock have a great ease visualizer which can help you decide what’s right for your animation.
Stop. Trigger Time
We have our audio and our animation ready. Now we just need to put it together and trigger it on a user interaction. We’ll wrap the audio and animation methods in a function:
Then, call that function on a click/touch event:
When the user clicks or touches the drum it’ll trigger the animation and the audio. The next step is to hook up the keyboard.
We can even animate the key guides when the keyboard is used:
Rinse and repeat this process for each drum in our kit.
Now we’ve got a fully functioning drum kit we can play with a mouse, keyboard or on touch. But let’s not stop here.
Program the Programmable (Beats)
We’ve got playable drums, but could make our drums programmable. We’re going to build a sequencer that can be programmed to play loops. This is potentially quite complicated, but again, it can be broken down into simple steps:
Create a “matrix” that represents the drums and time (or beats)
Cycle through the columns or beats
If a drum is active in the current beat, play the drum
Build the Matrix
“Unfortunately, no one can be told what the Matrix is. You have to see it for yourself.”
Fortunately, I can tell you exactly what our matrix is! It’s a simple grid where:
Rows will represent our drums
Columns will represent the beat
We need to be able to choose whether a drum is played or not on each beat in our sequencer. The <input> element with the type="checkbox" attribute is perfectly suited for this, however, it’s not that easy to style, but there’s a hack for that.
We’ll create a row for each drum and a column for each beat. In this demo we are going to use 8 beats. We’ll add a data-target-drum attribute (this could be called anything) with the name of our drum functions we created earlier. We can use the attribute to help us identify which corresponding function to call.
And the function to cycle through the “rows” and “beat” at a time looks as follows:
Timing is Everything
We’ve got a function to play our drums on the current beat. But we need to cycle through these beats. We can do this using the .setInterval() method.
It essentially defines the frequency (in milliseconds) with which the function should be executed. So we can use this to start the sequencer and set its speed. In musical terms the frequency of beats (or tempo) is typically referred to as bpm or beats per minute. So the bpm can be defined simply as the number of milliseconds in a minute divided by the bpm. We’ll set the bpm to a sensible default of 150. And then we set the interval when we click the play button.
That works great, but what about when we need to stop the sequencer? We can stop the sequencer by passing the ID returned from the .setInterval() method to the .clearInterval() method:
Go Fast, Go Slow
“All right. Let me go for a few bars. Come in soft, but then finish strong.”
It would be even more cool if we could change the bpm of our beats for faster or slower loops:
Phoning it in
A lot of mobile browsers not only ignore the preload="auto" but will actually only load the audio on a user touch event. This basically means that our sequencer won’t trigger any audio until it has already been triggered by the user. So we need to load the audio on the first user interaction. This is a bit a of a hack, but it means the sequencer will work on mobile devices.
That’s it! We’ve built a drum kit we can play and we can program to play by itself. I hope this tutorial has inspired you to create your own interactive, animated SVG. Using the same techniques you could build other musical instruments, or anything! If you do, please let me know, I’d love to see what you create!
Internet ExplorerSupported from version 11
Note that while the functionality works from IE 9 on, the layout for the demo is only supported by modern browsers.
GitHub link coming soon!
View demo Download source
How to Create an Interactive Animated SVG Drum Kit was written by Josh Ellis and published on Codrops.