Javascript to stop playing sound when another star

2020-02-13 06:43发布

So, I'm a complete amateur when it comes to coding, but I still like to fiddle around with it. I'm currently working on a html/jS/PHP based soundboard and I can't figure out how to stop sound from playing when pressing a button to play another one.

<script type="text/javascript" charset="utf-8">
        $(function() {
            $("audio").removeAttr("controls").each(function(i, audioElement) {
                var audio = $(this);
                var that = this; //closure to keep reference to current audio tag
                $("#doc").append($('<button>'+audio.attr("title")+'</button>').click(function() {
                    that.play();
                }));
            });
        });
    </script>

I hope someone understands that. Thanks in advance. There is also a PHP code to fetch the audio file automatically from the folder to the front end, probably unnecessary info for this problem.

标签: javascript
4条回答
你好瞎i
2楼-- · 2020-02-13 06:52

This is not very difficult to do if you use HTML5 which introduced the HTMLAudioElement.

Here is the minimal code for what you are trying to do:

// Let's create a soundboard module ("sb")
var sb = {
  song: null,
  init: function () {
    sb.song = new Audio();
    sb.listeners();
  },
  listeners: function () {
    $("button").click(sb.play);
  },
  play: function (e) {
    sb.song.src = e.target.value;
    sb.song.play();
  }
};

$(document).ready(sb.init);
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Audio</title>
</head>
<body>
  <button value="https://www.gnu.org/music/FreeSWSong.ogg">Song #1</button>
  <button value="https://www.gnu.org/music/free-software-song-herzog.ogg">Song #2</button>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</body>
</html>

You may also consider libraries like howler.js to help you in the development process.

查看更多
▲ chillily
3楼-- · 2020-02-13 06:53

Below code may help others:

var audioMap = new Map();
var rappers = document.querySelectorAll('.rapper');
rappers.forEach(function(rapper){
    audioMap.set(rapper, new Audio());
    rapper.addEventListener('click', function(){
        var audio = new Audio($(this).data('audio'));
        audio.play();
        audioMap.set(this, audio);
        var current = audioMap.get(this);
        // console.log('get', current);
        audioMap.forEach(function(audio){
            if( audio != current ){
                audio.pause();
                audio.currentTime = 0;
            }
        });
    });
});
查看更多
冷血范
4楼-- · 2020-02-13 06:57

You can stop and reset an audio element by pausing it and setting its current time to 0. You would need to do this whenever a button is clicked. Example:

// Available sounds:
const sounds = {
  "Bottle": "http://freewavesamples.com/files/Bottle.wav",
  "Bamboo": "http://freewavesamples.com/files/Bamboo.wav"
}

// Load audio elements:
let audios = {};
for (let [title, url] of Object.entries(sounds)) {
    audios[title] = new Audio(url);
}

// Create board buttons:
let board = document.getElementById("board");
for (let title of Object.keys(audios)) {
  let button = document.createElement("button");
  button.textContent = title;
  button.dataset["audio"] = title;
  board.appendChild(button);
}

// Handle board button clicks:
board.addEventListener("click", function(event) {
  let audio = audios[event.target.dataset["audio"]];
  if (audio) {
    // Pause and reset all audio elements:
    for (let audio of Object.values(audios)) {
      audio.pause();
      audio.currentTime = 0;
    }
    // Play this audio element:
    audio.play();
  }
});
<div id="board"></div>

In case you want to leverage the full power of the Web Audio API, you would probably start building your soundboard similar to this:

// Load buffer from 'url' calling 'cb' on complete:
function loadBuffer(url, cb) {
  var request = new XMLHttpRequest();
  request.open('GET', url);
  request.responseType = 'arraybuffer';
  request.onload = () => context.decodeAudioData(request.response, cb);
  request.send();
}

// Available sounds:
const sounds = {
  "Bottle": "url/to/bottle.wav",
  "Bamboo": "url/to/bamboo.wav"
};

let audioCtx = new (AudioContext || webkitAudioContext)(),
    board = document.getElementById("soundboard"),
    buffers = {},
    source;

// Load buffers:
for (let [title, url] of Object.entries(sounds)) {
  loadBuffer(url, buffer => buffers[title] = buffer);
}

// Create board buttons:
for (let title of Object.keys(sounds)) {
  let button = document.createElement("button");
  button.textContent = title;
  button.dataset["buffer"] = title;
  board.appendChild(button);
}

// Handle board button clicks:
board.addEventListener("click", function(event) {
  let buffer = buffers[event.target.dataset["buffer"]];
  if (buffer) {
    if (source) source.stop();
    source = audioCtx.createBufferSource();
    source.buffer = buffer;
    source.connect(audioCtx.destination);
    source.start();
  }
});
<div id="soundboard"></div>

Please note that the sound URLs given above must either be on the same domain or available under the same origin policy (see CORS headers).

查看更多
Explosion°爆炸
5楼-- · 2020-02-13 07:15

What you could do, is before start playing a new audio pause all available audio on the page. Something like this.

var audioOne = document.querySelector('#audio-1');
var audioTwo = document.querySelector('#audio-2');

var allAudios = document.querySelectorAll('audio');

function stopAllAudio(){
	allAudios.forEach(function(audio){
		audio.pause();
	});
}

document.querySelector('#play-1').addEventListener('click', function(){
	stopAllAudio();
	audioOne.play();
})
document.querySelector('#play-2').addEventListener('click', function(){
	stopAllAudio();
	audioTwo.play();
})
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<audio id="audio-1"
  src="http://developer.mozilla.org/@api/deki/files/2926/=AudioTest_(1).ogg">
</audio>
<audio id="audio-2"
  src="http://www.w3schools.com/html/horse.mp3">
</audio>

	<button id="play-1">
		play audio 1
	</button>
	<button id="play-2">
		play audio 2
	</button>	
</body>
</html>

Instead of adding audio using <audio> tag you could use HTMLAudioElement.

查看更多
登录 后发表回答