E archived  avatar

A javascript Piano(An invitation to review my code)

lizzyblue2

Published: 01 Oct 2020 › Updated: 01 Oct 2020A javascript Piano(An invitation to review my code)

A javascript Piano(An invitation to review my code)

In line with doing things on my own, yesterday I built a keyboard with vanilla Js. I watched a tutorial by WebDevSimplified on Youtube and saw that he used arrays for the white and black keys, but I had to break through the pattern of copying and decided to go with storing all my piano's information in an array of objects. I decided not to create the keys in my html, but instead to display them dynamically with javascript.

image.png

My html file is basically empty with just a placeholder div for the piano:

 <div class="piano"></div>

The piano looks like this:
https://liz-piano.netlify.app/

Nothing too fancy because I will be changing the css later.

Now, for the Javascript. I created an array of objects like I stated earlier to implement this in an OOP fashion. A snippet of this can be found here:

const data = [
  {
    keyColor: "white",
    keyNote: "C",
    keyAudio: "notes/C.mp3",
    keyLetter: "z",
  },
  {
    keyColor: "black",
    keyNote: "Db",
    keyAudio: "notes/Db.mp3",
    keyLetter: "s",
  },
  {
    keyColor: "white",
    keyNote: "D",
    keyAudio: "notes/D.mp3",
    keyLetter: "x",
  },
etc]

So there are 4 keys;keyColor, keyNote, keyAudio and keyLetter

I wrote a function for the data to be able to create the keys with a createPianoKey() function:

function createPianoKey(item) {
  const pianoKey = document.createElement("div");
  const { keyColor, keyNote, keyAudio, keyLetter } = item;
  const styles = ["key", keyColor];
  pianoKey.classList.add(...styles);
  piano.appendChild(pianoKey); 
}

I destructured each of the keys in my array of objects and stored them in the 'item'

I was looking for a way to add multiple styles to the keys and since I have .white and .black styles, at first I tried to add them in my array of styles, but for some reason the .black styles ended up overlapping. On reddit, someone suggested that I match the .key style with the keyColor key and this worked fine. That was a cool trick to know.

I wanted the keys to reflect the keyLetters since there was nothing in the html and so I added the following line in my fucntion:

pianoKey.innerHTML =

<span style='font-weight:bold;font-size:30px; color:teal; '>${keyLetter}</span>;

Next was thinking of how to add the sounds upon clicking the keys. I did the following:

const sound = new Audio();
 pianoKey.addEventListener("click", () => {
   sound.src = keyAudio;
   sound.play();
   pianoKey.classList.add("active");

   setTimeout(function () {
     pianoKey.classList.remove("active");
   }, 1000);
 });

I consoled.logged keyAudio, so I knew that each key was correctly associated with the audionote for the key. The setTimeout was necessary to remove the active class upon clicking the key.

I also wanted the user to be able to utilize their keyboard so I needed to write a keydown event listener function:

document.addEventListener("keydown", (e) => {
    if (e.key == keyLetter) {
      sound.src = keyAudio;

      sound.play();
      pianoKey.classList.add("active");

      setTimeout(function () {
        pianoKey.classList.remove("active");
      }, 1000);
    }

The keydown takes an event and if you write a simple console.log like :
console.log(key=${e.key},code=${e.code}); you will be able to see the keycode of every key you have pressed. Also, I could not add the eventListener directly on the pianoKey as I did with the clickListener because this event listener listens to the activities on the window. I hope this is a correct way of explaining things.

So, my entire function block looks like this:

data.forEach(createPianoKey);


function createPianoKey(item) {
  const pianoKey = document.createElement("div");



  const { keyColor, keyNote, keyAudio, keyLetter } = item;

  const styles = ["key", keyColor];
  pianoKey.classList.add(...styles);
  piano.appendChild(pianoKey);

  pianoKey.innerHTML = `${keyLetter}`;



  const sound = new Audio();
  pianoKey.addEventListener("click", () => {
    sound.src = keyAudio;
   

    sound.play();
    pianoKey.classList.add("active");

    setTimeout(function () {
      pianoKey.classList.remove("active");
    }, 1000);
  });

  document.addEventListener("keydown", (e) => {

    if (e.key == keyLetter) {
      sound.src = keyAudio;

      sound.play();
      pianoKey.classList.add("active");

      setTimeout(function () {
        pianoKey.classList.remove("active");
      }, 1000);
    }
  });
}


I have some repeated code which is visible in the following lines:

sound.src = keyAudio;
  

   sound.play();
   pianoKey.classList.add("active");

   setTimeout(function () {
     pianoKey.classList.remove("active");
   }, 1000);

I'm wondering if I could get some help refactoring those lines in a new function and also some suggestions on what could be done better using OOP principles.

please note I'm aware the css is not optimized for phones unless you auto-rotate. I have it in mind to code a 3d version of this, as I'm more focused on the Javascript bit.

Thanks!

Leave A javascript Piano(An invitation to review my code) to:

Written by

Movies

Read more #javascript posts


Best Posts From E archived

We have not curated any of lizzyblue2's posts yet. But you can encourage our curation team to review posts by visiting them regularly and by referring other readers. Because we give priority to frequently read content.

More Posts From E archived