DEV Community

Cover image for Build a Drum Kit Website
Abhishek Gurjar
Abhishek Gurjar

Posted on

Build a Drum Kit Website

Introduction

Hello, fellow developers! I'm excited to share my latest project with you: a Drum Kit. This project is a fun and interactive way to practice JavaScript, especially in handling user inputs and audio playback. Whether you're a beginner looking to dive into JavaScript or someone who loves music and coding, this project is perfect for you.

Project Overview

The Drum Kit is an interactive web application that simulates a drum set. Users can play sounds by clicking on the drum buttons or pressing corresponding keys on their keyboard. The project demonstrates how to work with events, audio, and CSS animations to create a responsive and engaging user experience.

Features

  • Interactive Drum Buttons: Clickable buttons that play different drum sounds.
  • Keyboard Controls: Press specific keys to trigger drum sounds.
  • Visual Feedback: Buttons animate when pressed, providing immediate visual feedback.
  • Responsive Design: The layout adjusts to different screen sizes, ensuring a consistent experience across devices.

Technologies Used

  • HTML: Provides the structure of the drum kit interface.
  • CSS: Styles the drum kit, including the button animations and overall layout.
  • JavaScript: Handles user interactions, sound playback, and animations.

Project Structure

Here's a quick look at the project structure:

Drum-Kit/
├── index.html
├── styles.css
└── index.js
Enter fullscreen mode Exit fullscreen mode
  • index.html: Contains the HTML structure of the drum kit.
  • styles.css: Includes CSS styles for the drum kit and animations.
  • index.js: Manages user interactions, sound effects, and animations.

Installation

To get started with the project, follow these steps:

  1. Clone the repository:

    git clone https://github.com/abhishekgurjar-in/Drum-Kit.git
    
  2. Open the project directory:

    cd Drum-Kit
    
  3. Run the project:

    • Open the index.html file in a web browser to see the drum kit in action.

Usage

  1. Open the website in a web browser.
  2. Click the drum buttons or press the corresponding keys (w, a, s, d, j, k, l) to play different drum sounds.
  3. Observe the button animations when pressed to get visual feedback.

Code Explanation

HTML

The index.html file sets up the structure of the drum kit, including buttons for each drum sound and a footer. Here’s a snippet:

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8" />
    <title>Drum Kit</title>
    <link rel="stylesheet" href="styles.css" />
    <link href="https://fonts.googleapis.com/css?family=Arvo" rel="stylesheet" />
  </head>
  <body>
    <h1 id="title">Drum 🥁 Kit</h1>
    <div class="set">
      <button class="w drum">w</button>
      <button class="a drum">a</button>
      <button class="s drum">s</button>
      <button class="d drum">d</button>
      <button class="j drum">j</button>
      <button class="k drum">k</button>
      <button class="l drum">l</button>
    </div>
    <script src="index.js" charset="utf-8"></script>
    <footer>Made with ❤️ by Abhishek Gurjar</footer>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

CSS

The styles.css file styles the drum kit, including the drum buttons and animations. Here are some key styles:

body {
  text-align: center;
  background-color: #283149;
}

h1 {
  font-size: 5rem;
  color: #DBEDF3;
  font-family: "Arvo", cursive;
  text-shadow: 3px 0 #DA0463;
}

footer {
  color: #DBEDF3;
  font-family: sans-serif;
}

.w { background-image: url("images/tom1.png"); }
.a { background-image: url("images/tom2.png"); }
.s { background-image: url("images/tom3.png"); }
.d { background-image: url("images/tom4.png"); }
.j { background-image: url("images/snare.png"); }
.k { background-image: url("images/crash.png"); }
.l { background-image: url("images/kick.png"); }

.set {
  margin: 10% auto;
}

.pressed {
  box-shadow: 0 3px 4px 0 #DBEDF3;
  opacity: 0.5;
}

.drum {
  outline: none;
  border: 10px solid #404B69;
  font-size: 5rem;
  font-family: 'Arvo', cursive;
  line-height: 2;
  font-weight: 900;
  color: #DA0463;
  text-shadow: 3px 0 #DBEDF3;
  border-radius: 15px;
  display: inline-block;
  width: 150px;
  height: 150px;
  text-align: center;
  margin: 10px;
  background-color: white;
}
Enter fullscreen mode Exit fullscreen mode

JavaScript

The index.js file controls the drum kit's functionality, including sound playback and button animations. Here’s a snippet:

const numberOfDrumButtons = document.querySelectorAll(".drum").length;

for (let i = 0; i < numberOfDrumButtons; i++) {
  document.querySelectorAll(".drum")[i].addEventListener("click", function () {
    const buttonInnerHTML = this.innerHTML;

    makeSound(buttonInnerHTML);
    buttonAnimation(buttonInnerHTML);
  });
}

document.addEventListener("keypress", function (event) {
  makeSound(event.key);
  buttonAnimation(event.key);
});

function makeSound(key) {
  switch (key) {
    case "w":
      const tom1 = new Audio("sounds/tom-1.mp3");
      tom1.play();
      break;
    case "a":
      const tom2 = new Audio("sounds/tom-2.mp3");
      tom2.play();
      break;
    case "s":
      const tom3 = new Audio("sounds/tom-3.mp3");
      tom3.play();
      break;
    case "d":
      const tom4 = new Audio("sounds/tom-4.mp3");
      tom4.play();
      break;
    case "j":
      const snare = new Audio("sounds/snare.mp3");
      snare.play();
      break;
    case "k":
      const crash = new Audio("sounds/crash.mp3");
      crash.play();
      break;
    case "l":
      const kick = new Audio("sounds/kick-bass.mp3");
      kick.play();
      break;
    default:
      console.log(key);
  }
}

function buttonAnimation(currentKey) {
  const activeButton = document.querySelector("." + currentKey);
  activeButton.classList.add("pressed");

  setTimeout(function () {
    activeButton.classList.remove("pressed");
  }, 100);
}
Enter fullscreen mode Exit fullscreen mode

Live Demo

You can check out the live demo of the Drum Kit here.

Conclusion

Building this Drum Kit was a fantastic experience that allowed me to dive into JavaScript's event handling and audio capabilities. I hope this project inspires you to experiment with interactive web applications and create your own fun and engaging projects. Feel free to explore the code, customize it, and use it in your own work. Happy coding!

Credits

This project was created to showcase JavaScript's potential for creating interactive web elements.

Author

Top comments (2)

Collapse
 
lionelrowe profile image
lionel-rowe

Fantastic project, love it!

A note about switch statements — variable declarations in each branch leak into other branches unless wrapped in a block.

switch (key) {
  case "w":
    const tom1 = new Audio("sounds/tom-1.mp3");
    tom1.play();
    break;
  case "a":
    // tom1 is still in scope here
    const tom2 = new Audio("sounds/tom-2.mp3");
    tom2.play();
    break;
}
Enter fullscreen mode Exit fullscreen mode

Fix:

switch (key) {
  case "w": {
    const tom1 = new Audio("sounds/tom-1.mp3");
    tom1.play();
    break;
  }
  case "a": {
    const tom2 = new Audio("sounds/tom-2.mp3");
    tom2.play();
    break;
  }
}
Enter fullscreen mode Exit fullscreen mode

But I think there's enough repeated code here that you might be better off with an object lookup:

function makeSoundObjLookup(key) {
  const lookup = {
    w: "tom-1.mp3",
    a: "tom-2.mp3",
    s: "tom-3.mp3",
    d: "tom-4.mp3",
    j: "snare.mp3",
    k: "crash.mp3",
    l: "kick-bass.mp3",
  };

  if (Object.hasOwn(lookup, key)) {
    new Audio(`sounds/${lookup[key]}`).play();
  } else {
    console.log(key);
  }
}
Enter fullscreen mode Exit fullscreen mode

There's still some collocated data missing here though, namely the images. You could collocate that data either by storing it in the HTML and reading from that in JS or by storing it in the JS and populating the DOM from that.

const lookup = {
  w: { sound: "sounds/tom-1.mp3", image: "images/tom1.png" },
  a: { sound: "sounds/tom-2.mp3", image: "images/tom2.png" },
  s: { sound: "sounds/tom-3.mp3", image: "images/tom3.png" },
  d: { sound: "sounds/tom-4.mp3", image: "images/tom4.png" },
  j: { sound: "sounds/snare.mp3", image: "images/snare.png" },
  k: { sound: "sounds/crash.mp3", image: "images/crash.png" },
  l: { sound: "sounds/kick-bass.mp3", image: "images/kick.png" },
};
Enter fullscreen mode Exit fullscreen mode

...or...

<div class="set">
  <button class="drum" data-sound="sounds/tom-1.mp3" style="background: url(images/tom1.png)">w</button>
  <button class="drum" data-sound="sounds/tom-2.mp3" style="background: url(images/tom2.png)">a</button>
  <button class="drum" data-sound="sounds/tom-3.mp3" style="background: url(images/tom3.png)">s</button>
  <button class="drum" data-sound="sounds/tom-4.mp3" style="background: url(images/tom4.png)">d</button>
  <button class="drum" data-sound="sounds/snare.mp3" style="background: url(images/snare.png)">j</button>
  <button class="drum" data-sound="sounds/crash.mp3" style="background: url(images/crash.png)">k</button>
  <button class="drum" data-sound="sounds/kick-bass.mp3" style="background: url(images/kick.png)">l</button>
</div>
Enter fullscreen mode Exit fullscreen mode

Or, if you can ensure the file names of the sound and image files are exactly in sync and that the extensions are always png or mp3, you can just store the name sans-extension.

const lookup = { w: "tom-1", a: "tom-2", s: "tom-3", d: "tom-4", j: "snare", k: "crash", l: "kick-bass" };

const sound = new Audio(`sounds/${lookup[key]}.mp3`)
const backgroundStyle = `background: url(images/${lookup[key]}.png)`
Enter fullscreen mode Exit fullscreen mode
Collapse
 
best_codes profile image
Best Codes

Cool and unique! I love it. ❤️