HTML5音频-重复播放声音点击,不管之前的迭代是否已经完成
HTML5 audio - play sound repeatedly on click, regardless if previous iteration has finished
我正在创建一个游戏,其中wav文件在点击时播放-在这种情况下,它是一声枪响"bang"。
问题是,如果我快速点击,它不会为每次点击播放一次声音-就好像在播放声音时忽略了点击,一旦声音完成,它又开始听点击。延迟似乎是1秒长,所以你认为如果有人每秒点击4或5次,我想要5次刘海,而不是1次。
这是我的HTML:
<audio id="gun_sound" preload>
<source src="http://www.seancannon.com/_test/audio/gun_bang.wav" />
</audio>
这是我的JS:
$('#' + CANVAS_ID).bind(_click, function() {
document.getElementById('gun_sound').play();
adj_game_data(GAME_DATA_AMMO_ID, -1);
check_ammo();
});
想法?
我知道这是一个很晚的答案,我只是想,但寻求一个解决方案,我发现,在我的情况下,最好的一个是预加载声音,然后克隆节点每次我想播放它,这允许我播放它,即使前一个还没有结束:
var sound = new Audio("click.mp3");
sound.preload = 'auto';
sound.load();
function playSound(volume) {
var click=sound.cloneNode();
click.volume=volume;
click.play();
}
一旦预加载了gun_bang.wav
,您就可以动态地制作带有该声音的新元素,播放音频,然后在音频完成时删除它们。
function gun_bang() {
var audio = document.createElement("audio");
audio.src = "http://www.seancannon.com/_test/audio/gun_bang.wav";
audio.addEventListener("ended", function() {
document.removeChild(this);
}, false);
audio.play();
}
$('#' + CANVAS_ID).bind(_click, function() {
gun_bang();
adj_game_data(GAME_DATA_AMMO_ID, -1);
check_ammo();
});
你可以用你自己的程序特定的点击逻辑来包装下面的代码,但是下面的代码同时演示了3种枪响。如果您想要任何类型的延迟,您可以引入一个较小的sleep()函数(很容易找到许多用于此的工具包),或者您可以使用setTimeout()来调用后续的函数。
<audio id="gun_sound" preload="preload">
<source src="http://www.seancannon.com/_test/audio/gun_bang.wav" />
</audio>
<script type="text/javascript">
jQuery(document).ready(function($){
$('#gun_sound').clone()[0].play();
$('#gun_sound').clone()[0].play();
$('#gun_sound').clone()[0].play();
});
</script>
HTML5音频元素有许多限制,它并不适合像游戏这样复杂的音频用例。
可以考虑使用WebAudio API。你必须:
-
使用
XMLHttpRequest
在缓冲区中加载音频文件 -
将缓冲区分配给
AudioBufferSourceNode
实例 -
将该节点连接到适当的目的地或中间节点(例如
GainNode
)。 -
如果你还需要停止声音,你需要跟踪每一个创建的源节点,还没有完成播放,这可以通过听源节点的
onended
来完成。
下面是一个封装了逻辑的类,它可以从URL加载声音,并根据需要多次播放/停止它,跟踪所有当前播放的源并在需要时清理它们:
window.AudioContext = window.AudioContext || window.webkitAudioContext;
const context = new AudioContext();
export class Sound {
url = '';
buffer = null;
sources = [];
constructor(url) {
this.url = url;
}
load() {
if (!this.url) return Promise.reject(new Error('Missing or invalid URL: ', this.url));
if (this.buffer) return Promise.resolve(this.buffer);
return new Promise((resolve, reject) => {
const request = new XMLHttpRequest();
request.open('GET', this.url, true);
request.responseType = 'arraybuffer';
// Decode asynchronously:
request.onload = () => {
context.decodeAudioData(request.response, (buffer) => {
if (!buffer) {
console.log(`Sound decoding error: ${ this.url }`);
reject(new Error(`Sound decoding error: ${ this.url }`));
return;
}
this.buffer = buffer;
resolve(buffer);
});
};
request.onerror = (err) => {
console.log('Sound XMLHttpRequest error:', err);
reject(err);
};
request.send();
});
}
play(volume = 1, time = 0) {
if (!this.buffer) return;
// Create a new sound source and assign it the loaded sound's buffer:
const source = context.createBufferSource();
source.buffer = this.buffer;
// Keep track of all sources created, and stop tracking them once they finish playing:
const insertedAt = this.sources.push(source) - 1;
source.onended = () => {
source.stop(0);
this.sources.splice(insertedAt, 1);
};
// Create a gain node with the desired volume:
const gainNode = context.createGain();
gainNode.gain.value = volume;
// Connect nodes:
source.connect(gainNode).connect(context.destination);
// Start playing at the desired time:
source.start(time);
}
stop() {
// Stop any sources still playing:
this.sources.forEach((source) => {
source.stop(0);
});
this.sources = [];
}
}
你可以这样做:
const soundOne = new Sound('./sounds/sound-one.mp3')
const soundTwo = new Sound('./sounds/sound-two.mp3')
Promises.all([
soundOne.load(),
soundTwo.load(),
]).then(() => {
buttonOne.onclick = () => soundOne.play();
buttonTwo.onclick = () => soundOne.play();
})
- 是否“;对于的“;循环迭代遵循JavaScript中的数组顺序
- 在对象上迭代以验证它是否's键存在于数组中
- 是否可以通过Javascript迭代stdin中的每个单词
- 对对象进行迭代,查看是否找到相同的值
- 如何验证for循环是否完成了node js中的所有迭代,循环是否包含带回调的函数调用
- Javascript数组中未定义的值是否使用任何内存或在for in循环中迭代
- 使用for.of迭代时删除集合中的元素是否安全
- 是否有可能在 JavaScript 中使用异步方法进行迭代
- ES6:在设置/映射迭代期间从集合/映射中删除元素是否危险
- 为..in - 被迭代的对象在进入循环之前是否只计算一次
- 是否可以在 ES6 Set 实例上使用数组迭代方法
- 迭代思考的javascript对象,看看它是否具有一定的价值
- 是否可以使用 CoffeeScript 迭代类的静态变量和方法
- 是否有一个 JavaScript 或 Lodash 函数可以轻松迭代成对或三元组
- JavaScript:是否可以迭代你的 OWN 变量
- 检查地图中是否有第一次迭代的方法
- 是否可以更改Struts'带有js的迭代器属性
- 是否可以通过JSON进行迭代来查找属性是否存在
- 是否有一种方法来迭代和显示json的键值对列表使用Handlebar.js
- HTML5音频-重复播放声音点击,不管之前的迭代是否已经完成