1

my goal is to build playing drums using vanilla Javascript, whole code worked perfectly when I was using only the keydown event, unfortunately, my drums have to play also on mouse 'click'. When I added "|| event.button == aKey == 0" this part to my condition, it still plays, but only one sound on each key. So I assumed that there is something wrong with my condition.

And also if it would be possible to somehow make my code less repeatable, I would appreciate it.

const aKey = document.getElementById("A-key");
const sKey = document.getElementById("S-key");
const dKey = document.getElementById("D-key");
const fKey = document.getElementById("F-key");
const gKey = document.getElementById("G-key");
const hKey = document.getElementById("H-key");
const jKey = document.getElementById("J-key");
const kKey = document.getElementById("K-key");
const lKey = document.getElementById("L-key");

const playFunction = (event) => {
    if (event.code == "KeyA" || event.button == aKey == 0) {
        // 
        let audioA = document.createElement("AUDIO");
        if (audioA.canPlayType("audio/wav")) {
            audioA.setAttribute("src","sounds/boom.wav");
        }
        audioA.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioA);

    } else if (event.code == "KeyS" || event.button == sKey == 0 ) {

        let audioS= document.createElement("AUDIO");
        if (audioS.canPlayType("audio/wav")) {
            audioS.setAttribute("src","sounds/clap.wav");
        }
        audioS.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioS);

    } else if (event.code == "KeyD" || event.button == dKey == 0) {

        let audioD = document.createElement("AUDIO");
        if (audioD.canPlayType("audio/wav")) {
            audioD.setAttribute("src","sounds/hihat.wav");
        }
        audioD.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioD);

    } else if (event.code == "KeyF"  || event.button == fKey == 0) {
        let audioF = document.createElement("AUDIO");
        if (audioF.canPlayType("audio/wav")) {
            audioF.setAttribute("src","sounds/kick.wav");
        }
        audioF.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioF);

    } else if (event.code == "KeyG" || event.button == gKey == 0) {
        let audioG = document.createElement("AUDIO");
        if (audioG.canPlayType("audio/wav")) {
            audioG.setAttribute("src","sounds/openhat.wav");
        }
        audioG.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioG);

    } else if (event.code == "KeyH" || event.button == hKey == 0) {
        let audioH = document.createElement("AUDIO");
        if (audioH.canPlayType("audio/wav")) {
            audioH.setAttribute("src","sounds/ride.wav");
        }
        audioH.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioH);

    } else if (event.code == "KeyJ" || event.button == jKey == 0) {
        let audioJ = document.createElement("AUDIO");
        if (audioJ.canPlayType("audio/wav")) {
            audioJ.setAttribute("src","sounds/snare.wav");
        }
        audioJ.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioJ);

    } else if (event.code == "KeyK" || event.button == kKey == 0) {
        let audioK = document.createElement("AUDIO");
        if (audioK.canPlayType("audio/wav")) {
            audioK.setAttribute("src","sounds/tink.wav");
        }
        audioK.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioK);

    } else if (event.code == "KeyL" || event.button == lKey == 0) {
        let audioL = document.createElement("AUDIO");
        if (audioL.canPlayType("audio/wav")) {
            audioL.setAttribute("src","sounds/tom.wav");
        }
        audioL.setAttribute("autoplay", "autoplay");
        document.body.appendChild(audioL);
    } else {
        console.log("Try to use specified keys.")
    }
};

window.addEventListener('keydown', playFunction, false);
window.addEventListener('click', playFunction, false);
2
  • event.button == aKey == 0 mean that event.button must be equal to akey that must be equal to 0... Just use event.button == aKey after || Commented Jun 16, 2021 at 15:43
  • I tried that on start, but it doesn't play by mouse click at all if the condition looks like this: event.button == aKey Commented Jun 16, 2021 at 15:47

1 Answer 1

1

event.button == kKey == 0 doesn't make much sense. This evaluates like (foo == bar) == baz, that is, the first condition is tested, then the result of that (true or false) is checked against the other condition. If you want to test multiple conditions, use || or && between every condition. Also, always use === to avoid surprising conversion behavior.

As for the refactor request, whenever you have a bunch of branches that only differ based on parameterizable values, like the button text or the sound, use a data structure such as an array or object and index/key into it.

Specifically, all you need here are key -> audio or audio URL pairs, so an object seems suitable.

Once you have such a structure, then you can access the power of loops to DRY out your code.

I don't have your audio files or markup, so you can try to adapt this proof of concept to your project:

const baseURL = `https://upload.wikimedia.org/wikipedia/commons/`;
const sounds = {
  a: `7/7c/Bombo_Leg%C3%BCero_Grave.ogg`,
  s: `7/7f/Bombo_Ac%C3%BAstico.ogg`,
  d: `3/35/Bongo_Agudo.ogg`,
  f: `4/44/Bongo_Grave.ogg`,
  g: `b/b4/Sting.ogg`,
  // ... add more key-sound URL pairs ...
};

Object.keys(sounds).forEach(key => {
  const btn = document.createElement("button");
  document.querySelector("#drum-pad").appendChild(btn);
  const sound = new Audio(baseURL + sounds[key]);
  sounds[key] = sound;
  btn.textContent = key;
  btn.addEventListener("click", e => {
    sound.currentTime = 0;
    sound.play();
  });
});

document.addEventListener("keydown", e => {
  if (sounds[e.key]) {
    sounds[e.key].currentTime = 0;
    sounds[e.key].play();
  }
});
<div id="drum-pad"></div>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.