JavaScript Drum kit ๐Ÿฅ: Day 1 #JavaScript30

Listen to this article

๐Ÿ‘‹ Hello people!

In this blog, we will be building a JavaScript Drum kit. Which plays a specified sound based upon the key pressed. Check the live demo & play some music ๐ŸŽต๐ŸŽน that's the only way around to understand what's happening.

The starter files for this project can be found here.

๐Ÿง  HTML && CSS

First up, let's check the HTML and CSS from the starter files, given above. HTML file has a div element with class = keys and several inner div with class = key. Each div has attribute data-key set to a specific keycode. Every key in keyboard has a unique keycode, use keycode.info to find keycodes. And <kbd> element is used to represent the corresponding keys.

Example:

    <div data-key="65" class="key">
        <kbd>A</kbd>
        <span class="sound">clap</span>
    </div>

Further, sound that should be played for the corresponding key is linked using <audio data-key=$> element. Where $ is the corresponding keycode.

Coming to CSS part, it has .playing class , which will scale up the element & change border-color. This class will be applied depending upon the key pressed and will be removed once the transition is done.

๐Ÿšด Approach

Before writing JavaScript, let's see what we have to accomplish. Upon hitting the keys specified above, the corresponding element on screen should play it's sound and also border-color should change to yellow, with animation. In the styles written for .key class, transition: all 0.07s ease is responsible for adding transition animation. Increasing or decreasing the time from 0.07 seconds will change the speed of animation accordingly. Play around with it, to find a value for your liking.

๐Ÿ’› JavaScript

Let's divide the task into steps from here on, for simplicity.

Step 1: Adding eventListener

Inside the window object we add an eventListener. It takes two arguments, the event to listen, keydown and the function to call, playSound. Lets define this function in next step.

window.addEventListener('keydown', playSound)

Step 2: Creating playSound function

The playSound function will accept one parameter i.e, event. Declare and define two variables audio and key that will correspond to the keypress. If the entered key matches the keys defined, go ahead and add .playing class to it. If it doesn't, return.

function playSound(e) {
    const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    const key = document.querySelector(`.key[data-key="${e.keyCode}"]`);
    audio.currentTime = 0;
    audio.play();
    if (!audio) return;
    key.classList.add('playing')
}

Here audio.currentTime = 0 is to repeatedly play the audio upon hitting the same key. Try removing this line and find out the difference.

Step 3: Removing the Transition

After step two, .playing class is added to each div element on correct keypress, which gives a styling of yellow border around the elements. But if we notice its not removed once the event is ended. We need to iterate through each HTML element and add an eventListener on every transitionend event.

const keys = document.querySelectorAll('.key');
keys.forEach(key => key.addEventListener('transitionend', removeTransition));

Here removeTransition is defined just like playSound function but this time to remove the .playing class.

  function removeTransition(e) {
    if (e.propertyName !== 'transform') return; 
    this.classList.remove('playing')
  }

The if condition makes sure that function doesn't run for any event other than transform events. That's it we are done ๐ŸŽ‰. The end code looks something like this.

  function playSound(e) {
    const audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    audio.currentTime = 0;
    audio.play();
    if (!audio) return;
    key.classList.add('playing')
  }

  function removeTransition(e) {
    if (e.propertyName !== 'transform') return; 
    this.classList.remove('playing')
  }

  window.addEventListener('keydown', playSound);
  const keys = document.querySelectorAll('.key');
  keys.forEach(key => key.addEventListener('transitionend', removeTransition));

๐ŸŒŸAdditional Features

We can play the sounds even with the mouse clicks and touch input. To do this, add another eventListener, but this time listen to mousedown event and call a clickTrigger function ( quite similar to playSound function).

The above page looks good in desktop but in mobile devices, the keys tend to over lap. To correct that add below properties to .key in CSS.

.keys {
    flex-wrap : wrap;
    align-content-center;
}

Few more additions for mobile devices

* {
    /* Disables the double tap to Zoom  */
  touch-action: manipulation;
}
.key {
    /* turns mouser pointer into hand when hovered */
    cursor: pointer
    /* disables the double click to select */
    user-select: none;
}

The Additional lines of CSS added is to fine-tune the experience in mobile. Else, multiple clicks, are either treated as select in a web browser and zoom in a mobile browser. That's the end of it. You can refer to my code here if you're stuck.

๐ŸคThank you for reading.

I hope, to the end you have managed to build a cool Javascript drum kit. I'm new to writing a technical article, do let me know if I have erred somewhere. Feel free to drop a comment, if anything can be done better or any more features can be added. See you in my next blog. Until then,

Bye !

References:

The course, from which the project is picked.

MDN: addEventListener

MDN: kbd

No Comments Yet