DEV Community

Cover image for Virtual Drum Kit using Javascript
prashanth
prashanth

Posted on • Updated on

Virtual Drum Kit using Javascript

Hello everyone,

Hope you all are safe during this pandemic. I have started a new series where I will be posting Javascript projects for beginners.

Each post in this series mainly comprises of two things,

       1. TIL while building them.
       2. Project explanation.
Enter fullscreen mode Exit fullscreen mode

So Let's start,

What we are gonna build today is a Virtual Drum which,

       1. Has visual representation of the keys
       2. Plays a audio file when pressing its 
          corresponding key
       3. A small animation indicating that the particular 
          key is pressed - Scales up(make it appear big)  
          for a fraction of a second and scales down while 
          maintaining a smooth transition.
Enter fullscreen mode Exit fullscreen mode

Alt Text

TIL

1. transitionend

It is an event Listener which gets triggered when the transition gets over as the name specifies. To know its use case read the entire post.

2. data-*

Data attribute allow authors to create custom data to apply to their HTML elements to store extra data. They help extend the information that HTML can communicate to script.

3. defer vs window.onload

Both are used to load the script after the document has finished parsing inorder to prevent the script accessing the DOM elements even before parsing stage is over. Using defer and window.onload are not the same even though they serve the same purpose of loading script. Load events are triggered only after deferred scripts run.

4. background-size

  1. cover:
    Resize the background image to cover the entire container, even if it has to stretch the image or cut a little bit off one of the edges

  2. contain:
    Resize the background image to make sure the image is fully visible

  3. auto:
    Default value. The background image is displayed in its original size

Project Explanation

<div class="parent-key">
  <div data-key=65 class="key">
    <div>A</div>
    <span>Clap</span>
  </div>
</div>

<audio data-key=65 src="sounds/boom.wav"></audio>
Enter fullscreen mode Exit fullscreen mode

This is the basic markup for a single key and its corresponding audio. audio is the tag which is used to include sound in html . It has got the audio api which can be used to manipulate the audio file to play, pause, reset ... and much more. Data-*(data attribute) has the value equivalent to the ASCII value of the key.

body {
    background-image: url('background.jpg');
    background-size: cover;
}

.parent-key {
    display: flex;
    justify-content: space-around;
    align-items: center;
    min-height:100vh;
    flex-wrap: wrap;
}


.key {
    color: white;
    font-size: 40px;
    border:3px solid black;
    background-color: rgba(0,0,0,0.4);
    padding: 10px;
    text-align: center;
    text-transform: uppercase;
    letter-spacing: .1rem;
    transform: scale(1);
    transition: all 0.2s ease;
}

.key span {
    font-size: 14px;
    color: #ffc600;
}

.playing {
    transform: scale(1.2);
    border: 4px solid #ffc600;
    box-shadow: 0 0 1rem #ffc600;
}
Enter fullscreen mode Exit fullscreen mode

For the styling part of the markup, I have used flex to center align the keys vertically and horizontally. Background image is included using the url .For remote image, url is specified and for image available in your directory, path is specified.The class playing is added to the element when the key corresponding to the key in the UI is pressed and removed after a fraction of a second. The class playing makes the element bigger in size(transform: scale(1.2)), applies larger border and box-shadow(highlights the box).

Till now we have completed the markup and styling part. Now let's give functionality to the virtual drum kit. When a key is pressed,

          1. Play the ``audio``
          2. Attach the class ``playing``
          3. Remove the class ``playing`` after the 
             transition is over.
Enter fullscreen mode Exit fullscreen mode

Let's attach an eventListener(keydown) to the window object so that whenever a key is pressed the eventListener gets triggered and the function execution starts. We should execute the function only if you press the keys for which the audio must be played, so let's give a if-check which looks for the audio element in the html file using the keyCode corresponding to the key pressed.


window.addEventListener('keydown',function(e){
   let audio = document.querySelector(`audio[datakey="${e.keyCode}"]`)
   if(!audio) return;
})

Enter fullscreen mode Exit fullscreen mode

Using the audio element we now can play the audio using the play method in the audio element api- audio.play(). when you run the code , when you press the key you want to play the audio file , audio is played but there is a problem here. Lets say the audio file is for 3 seconds for a particular beat, you cannot be waiting till the audio file finishes(in the case you want to press the same key multiple times),so we must reset the time to zero(audio.currentTime = 0;).By now, if you press the audio keys we can hear the corresponding sound.

But we need some animation to indicate that the particular key is pressed. This can be done by adding the class playing to pressed key element with a smooth transition using the transition property in css. Get the key from the document api and add the class to it.

window.addEventListener('keydown',function(e){
    if(!document.querySelector(`audio[data-key="${e.keyCode}"]`)) return;
    let audio = document.querySelector(`audio[data-key="${e.keyCode}"]`);
    let key = document.querySelector(`.key[data-key="${e.keyCode}"]`)
    audio.currentTime = 0;
    audio.play();
    key.classList.add('playing');
})
Enter fullscreen mode Exit fullscreen mode

Now when we press the key, the key element in UI scales up, but we need to scale down by removing playing class after a fraction of second. One way of doing this using setTimeout function. Using this function we can delay for a fraction of a second of a second and remove the class. It works fine but the issue we will face is, sometimes it messes up with the transition property in css(transition: all .07s ease;). The better way of handling this situation is listening to transitionend event, which executes a function when the transition ends. So now we can remove the class playing after the transition gets over.


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

let keys = document.querySelectorAll('.key');
keys.forEach((key)=>{
    key.addEventListener('transitionend',function(){
        this.classList.remove('playing')
    })
})
Enter fullscreen mode Exit fullscreen mode

I hope you were able to learn how to make a virtual drum. Follow me to read more javascript projects and don't forget to like because it will motivate me πŸ˜‰.

Assets(audio files and background image) and code files available in this repoπŸ‘‡πŸ»

GitHub logo prashanthsasidharan / javascript-projects

This repo consist of assets and code files for every js project I create.

javascript-projects

This repo consist of assets and code files for every js project I create.


Header Image By PlayTheTunes

Top comments (0)