我正在开发钢琴应用程序。我有一个带有音符名称和播放时间的json数组。
var data= [{"duration":300,"value":"2C"},{"duration":400,"value":"2D"},{"duration":420,"value":"2E"},{"duration":600,"value":"2F"},{"duration":400,"value":"2G"}];
我需要播放2C音符300微秒,2D音符播放400微秒,2E播放420,依此类推,即在完成前一个音符后播放下一个音符。
我有.ogg格式的所有音符的音频文件,所有音符都有相同的持续时间1018.776微秒。
为了播放上面json数据的注释,我尝试了javascript的setTimeout函数:
$.each( data, function( key, value ) {
setTimeout(function(){
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
audioElement.play();
}, value.duration*key);
});
但这不起作用。主要问题是持续时间。当我使用console.log(value.value)时,结果是2C,2D,2E,2G,2F。这里2F和2G的顺序不正确。 那么,如何以正确的顺序播放这些音符及其各自的持续时间?
答案 0 :(得分:4)
您需要使用递归函数而不是循环:
function playNotes(notes) {
var i = 0;
playNextNote();
function playNextNote() {
if (i < notes.length) {
var value = notes[i];
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
audioElement.play();
i++;
setTimeout(playNextNote, value.duration);
}
}
}
这样,在当前音符完成之前,不会触发下一个音符开始播放。
答案 1 :(得分:0)
更喜欢在超时后调用其他值。
function callAudio (index) {
var
value = this[i],
audioElement = document.createElement('audio');
if (!value) return;
audioElement.setAttribute('src', './audio/'+value.value+'.ogg');
audioElement.play();
setTimeout(callAudio.bind(this, index++), value.duration);
};
callAudio.call(data, 0);
答案 2 :(得分:0)
您可以使用接收数组和索引的函数,然后在延迟后使用下一个索引调用自身。
var data= [{"duration":300,"value":"2C"},{"duration":400,"value":"2D"},{"duration":420,"value":"2E"},{"duration":600,"value":"2F"},{"duration":400,"value":"2G"}];
function playNote(data, index) {
var audioElement = document.createElement('audio');
audioElement.setAttribute('src', './audio/'+data[index].value+'.ogg');
audioElement.play();
if (index + 1 < data.length) {
setTimeout(function() {
playNote(data, index + 1);
}, data[index].duration);
}
}
playNote(data, 0);
答案 3 :(得分:0)
您正在使用此代码进行一些假设 - 我看到的第一个假设是声音文件立即加载。你可能遇到的问题是循环没有跟踪到目前为止的延迟 - 所以基本上你正在调用setTimeout({play},400)并且紧接在setTimeout({play},500之后)所以他们最终500ms后重叠直到800 ms。
我写出我认为你正在寻找的东西是这样的:
var audio = $.map(data, function(key,val) {return $("<audio>",{src:val.value})});
audio.each(function(indx, $ele) {
if(indx !=0){
audio[indx-1].on("ended", function(){$ele.get().play()});//play next sound when previous one finishes playing
}
});