All Articles

Drumkit using JavaScript

Projects are the best way to learn to program. They bring theoretical nonsense into the real world and make it tangible. Instead of reading about how to create a loop statement instead you’re making them and they’re doing cool things in the browser.

That’s why JavaScript30 is such a great concept. Wes Bos has released this free course that walks you through 30 projects using vanilla JavaScript. The tagline is:

Build 30 things in 30 days with 30 tutorials No Frameworks | No Compilers | No Libraries | No Boilerplate

Sounds pretty awesome right? You can join me or see more about each project here


Day 1 - JavaScript Drum Kit

Today we will be creating an ‘electric drum kit’ that is controlled by the keyboard. The project itself will require some basic animation and linking Javascript Event Keycodes up to sounds.

This is the first time I am coming into contact with data-attributes (or more to the point the first time I’m looking into what these random attribute tags are). This is a super extendable way of associating data with a particular HTML element and making it accessible to JavaScript and CSS (perfect for this use case). We are using the data attribute data-key on each of the button divs & audio elements to link them to the associated keyCode.

To link this all together we will need to add an event listener to the window that listens for keydown events. Each time a key on the keyboard is pressed it sends a whole bunch of data to the browser. One of these values is the keyCode. Once we have the user input via the event listener we can check to see if this matches any of the data-attributes on our audio/buttons. If it does we can just call play() on it.

Boom. The first iteration of our JavaScript Drum kit is working!

Drumkit Version 1

There are a few problems with it that we still need to iron out:

  • If an audio file is already playing then we can’t play it again (hitting the same key in quick succession is needed for a good drum kit).
  • There is no visual indication that we have hit a key.

Play the Audio File in Quick Succession

Fixing the audio file not being able to play in quick succession is a quick fix.

Before calling audio.play(); we ‘rewind’ the track to the beginning:

    window.addEventListener('keydown', function (e) {  
    //Select the audio = to keydown event & set it to audio variable
    const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    //If there is no associated audio stop the function
    if (!audio) return;
    //Rewind the current audio track to start
    audio.currentTime = 0;
    //Play the audio
    audio.play();
    });
Visual Indication of Key Down Event

Now for the visual representation of the keydown event. In the style.css that Wes provided there is a playing class selector that scales the div up, changes the border colour and creates a darker box-shadow. We need to apply this class to the div when the keydown event for one of our registered keyCodes is completed. We can do this using the classList property:

    //Select the key div =  to keydown event & set it to key variable
        const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
        //Add the styling class 'playing' to the active key div.
        key.classList.add('playing');

This works well but there isn’t a function that removes the ‘playing’ class once it has been applied:

Still need to remove the animation

To do this we will listen for ’transitionend’ on each of the keys. When this returns true we will then remove the playing class from the div.

This looks like:

    function removeTransition(e) {  
      //event returns several results. We chose 'transform' to listen for
      if (e.propertyName !== 'transform') return
      this.classList.remove('playing')
    }
    
    const keys = document.querySelectorAll('.key')  
    keys.forEach(key => key.addEventListener('transitionend', removeTransition))  

Now everything is working just fine (yay):

Final drumkit


Now that everything has been done I have pushed this project live to a Firebase project. You can view it live here.