๐ 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.