Click here to Skip to main content
15,882,017 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Please I am new to JavaScript. I am trying to build a free mini game for some kids that will help to teach them what the name of a some baby animals are called. I have a list of 22 animals each in a div element. I want a predefined audio to be played for each div element clicked.

I have tried listing the first two audio in an array, it works fine when the first div element is clicked. But when the second div element is clicked, both audios in the array play at the same time.

I have read some answers to some related questions here but I haven't got a clear solution. I have also tried using variables for each audio instead of putting them in array and the issue did not change. I have also attempted to pause each previous sound while a new sound is fired, but I know that would be a verbose chunk of code and there could a better way to achieve this.

Here is my code, I feel there is something I am not doing well. Please assist me. Thank you.


What I have tried:

  <div class="container-fluid border">
            <div class="cards-box row ">
                <div class="cards border animate__animated animate__fadeIn" id="card1" onclick="beer()">Beer</div>
                <div class="cards border " id="card2" style="display:none;" onclick="bee()">Bee</div>
                <div class="cards border " id="card3" style="display:none;" onclick="bird()">Bird</div>
            </div>
        </div>

<script>
var voiceOfSonia = [
  new Audio("./audio-files/Beers.mp3"),
  new Audio("./audio-files/bee.mp3")
];
let clickSound = new Audio("./audio-files/click.wav");
let pix1 = document.getElementById("card1");
pix1.addEventListener("click", beer);
let pix2 = document.getElementById("card2");
pix2.addEventListener("click", bee);

function beer() {
        clickSound.play();
  clickSound.volume = 0.3;
  clickSound.addEventListener("ended", function () {
    voiceOfSonia[0].play();
    voiceOfSonia[0].volume = 0.5;
    voiceOfSonia[0].addEventListener("ended", function () {
      document.getElementById("card2").style.display = "block";
    });
  });
}


function bee() {
  clickSound.play();
  clickSound.volume = 0.3;
  clickSound.addEventListener("ended", function () {
    voiceOfSonia[1].play();
    voiceOfSonia[1].volume = 0.5;
    voiceOfSonia[1].addEventListener("ended", function () {
      document.getElementById("card3").style.display = "block";
    });
Posted
Updated 19-Jun-22 23:01pm

1 solution

First problem: you're using both the onclick="..." attribute and the addEventListener method. Your event handlers are being wired up twice to the same event. Get rid of the onclick attributes, and stick to the addEventListener approach.

Second problem: you're wiring up a handler to the ended event of the clickSound, but you never remove it. Each time you click, you add another handler to the same event. You need to specify the once option to prevent the handler from being fired more than once.

Third problem: you need to set the properties and add the event listener before playing the sound.

EventTarget.addEventListener() - Web APIs | MDN[^]

Try something like this:
HTML
<div class="container-fluid border">
    <div class="cards-box row ">
        <div class="cards border animate__animated animate__fadeIn" id="card1">Beer</div>
        <div class="cards border " id="card2" style="display:none;">Bee</div>
        <div class="cards border " id="card3" style="display:none;">Bird</div>
    </div>
</div>
JavaScript
function createVoice(name, nextCard) {
    const result = new Audio("./audio-files/" + name + ".mp3");
    result.volume = 0.5;
    
    if (nextCard) {
        result.addEventListener("ended", function(){
            document.getElementById(nextCard).style.display = "block";
        });
    }
    
    return result;
}

const voiceOfSonia = [
    createVoice("Beers", "card2"),
    createVoice("bee", "card3"),
    createVoid("bird")
];

const clickSound = new Audio("./audio-files/click.wav");
clickSound.volume = 0.3;

function playVoice(index){
    clickSound.addEventListener("ended", function () { voiceOfSonia[index].play(); }, { once: true });
    clickSound.play();
}

document.getElementById("card1").addEventListener("click", function(){ playVoice(0); });
document.getElementById("card2").addEventListener("click", function(){ playVoice(1); });
document.getElementById("card3").addEventListener("click", function(){ playVoice(2); });
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900