user19147296
user19147296

Reputation:

Playing sound with no click interaction within JS doesn't work?

Solved! with ADDED critical INFO:

Found that the cause is finding the sound when using js, versus html (which does! work.)

FINALLY fixed the correct Path ...

/*
   Correct PATH:
      games
         Game_1
            Game_1_Support
               audio
                  applause.mp3
               js
                  PlaySound.js

*/
    PlaySound("Game_1_Support/audio/applause.mp3");

function PlaySound(id, src) {

    var theSound = new Audio();
    theSound.src = src;
    alert(src);
    
    theSound.play();
    
}

Thanks! absolutely everyone!

END ADDED INFO

Playing sound with no click interaction within JS doesn't work?

Very old subject based on my research and this research states the user must interact via clicking, e.g., in order for the sound to be played via:

var theSound = new Audio(srcString);
theSound.play();

In the game I am currently developing, upon my clicking a <a>, the sound does play.

But ... my game also has a ball that moves around the inside of the window and if the ball hits any of the window's sides, I want a sound to play.

No clicking is involved, just my moving the ball around via certain keys, e.g., "r" and "l".

So how do I do this within JS with no clicking?

Upvotes: 0

Views: 2700

Answers (4)

chrwahl
chrwahl

Reputation: 13060

Now that this is a game it is important that all the assets (audio, images, scripts) are loaded and ready before the game is playing. Never create a new audio object and then call play() immediately after. You need to wait till the file is loaded or the file can play (in the case of audio and video).

In the example I have created a function loadaudio() that returns a promise of an audio object. If there are many assets like this, they should go into the array and when they all are resolved the game can start.

Then there is the issue with the user interaction (issue described here: https://stackoverflow.com/a/62720714/322084). I made a button that when clicked starts the game. After the use have clicked the button any audio element can play at anytime.

var globalassets = [];

const loadaudio = (id, src) => {
  return new Promise((resolve, reject) => {
    let audio = new Audio();
    audio.id = id;
    audio.oncanplay = resolve(audio);
    audio.onerror = reject(audio);
    audio.src = src;
  });
};

const initgame = assets => {
  globalassets = assets;
  console.log('initiate game');
  document.getElementById('start').classList.remove('hidden');
};

const onstatbtn = e => {
  console.log('game is playing');
  globalassets.find(asset => asset.id = 'a1').play();
};

document.addEventListener('DOMContentLoaded', e => {
  let assets = [
    loadaudio('a1','https://upload.wikimedia.org/wikipedia/commons/6/61/Wellerman.wav')
  ];
  Promise.all(assets).then(initgame);
  
  document.getElementById('start').addEventListener('click', onstatbtn);
});
.hidden {
  display: none;
}
<button id="start">Start game</button>

Upvotes: 0

altoqueperro
altoqueperro

Reputation: 379

check this example , use canplay event then init your game,then inside the event just call play() method, notice that if you never focus the window the sound will be never reproduce, if you have troubles for init the sound after an trusted event need to be fired, you could use a trick , put a click event on your document;

document.addEventListener("click",()=>{
  sound.volume = 0;
  sound.play();
  sound.pause();
  sound.volume = 1;
  sound.currentTime = 0;
  // here remove your listener to avoid multiple calls 
});

<html>
<body>
  <div style="width:300px;height:300px;border:1px solid;position:relative;">
    <div id="ball" style="width:10px;height:10px;background-color:blue;position:absolute;top:100px;">
    
    </div>
  </div>
<script>

 let sound= new Audio("https://actions.google.com/sounds/v1/alarms/beep_short.ogg");
 sound.oncanplay = function(){
 let ball = document.getElementById("ball");
  let i = 0;
  setInterval(()=>{
    i= i+10;
    ball.style.left = i+"px";
    if(i>280){
     i=0;
     sound.play();
    }
  },200);
};
  
  
</script>
</body>
</html>

Upvotes: 0

Brad
Brad

Reputation: 163272

You don't necessarily need a click event. You just need a trusted event. A keypress event is good enough for starting audio.

Upvotes: 1

chrwahl
chrwahl

Reputation: 13060

You should wait calling play() until the audio object is ready.

HTMLMediaElement: canplay event - Web APIs | MDN

const audio = new Audio('https://upload.wikimedia.org/wikipedia/commons/6/61/Wellerman.wav');

audio.addEventListener('canplay', e => {
  console.log('canplay');
  audio.play();
});

Upvotes: 1

Related Questions