设置超时功能,具有钢琴应用程序的动态持续时间
setTimeout function with dynamic duration for Piano Application
我正在开发一个钢琴应用程序。我有一个带有音符名称及其播放时间的 json 数组。
var data= [{"duration":300,"value":"2C"},{"duration":400,"value":"2D"},{"duration":420,"value":"2E"},{"duration":600,"value":"2F"},{"duration":400,"value":"2G"}];
我需要按顺序播放 300 微秒的 2C 音符、400 微秒的 2D 音符、420 秒的 2E 等,即在完成上一个音符后播放下一个音符。
我为所有笔记提供了.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 的顺序不正确。那么,如何以正确的顺序和各自的持续时间演奏这些音符呢?
你需要使用递归函数而不是循环:
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);
}
}
}
这样,在当前音符完成之前,不会触发下一个音符开始播放。
您可以使用接收数组和索引的函数,然后在延迟后使用下一个索引调用自身。
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);
更喜欢在超时后调用其他值。
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);
你用
这段代码做了几个假设 - 我看到的第一个假设是声音文件会立即加载。您可能遇到的问题是循环到目前为止没有跟踪延迟 - 所以基本上你调用 setTimeout({play}, 400) 并在 setTimeout({play}, 500) 之后立即调用,因此它们最终在 500 毫秒后重叠到 800 毫秒。
我会写我认为你正在寻找的东西的方式是这样的:
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
}
});
相关文章:
- 如何在AngularJS应用程序的主体上动态设置溢出
- 动态代码中存在系统应用程序地址错误
- React Rails应用程序中动态子项的密钥分配问题
- 管理动态磁贴和应用程序生命周期
- 根据角度 js 应用程序中的条件动态添加类
- 谷歌应用程序脚本web应用程序动态列表从表单
- ASP中的动态图像.NET Web应用程序
- 动态加载AngularJS应用程序
- Facebook选项卡应用程序动态URL
- Slick Carousel在应用程序动态路由的基础上不起作用
- 如何使用chrome应用程序窗口动态调整文本区域的大小
- MusicBrainz应用程序|AngularJS的JSON对象的动态GET
- jsf应用程序中的动态javascript
- Handlebar.js模板,使用Undercore.js-Zendesk应用程序进行动态表单输入
- Dojo中的动态内容单页应用程序
- web应用程序——动态加载/卸载Javascript
- Windows应用商店应用程序:动态加载JavaScript以便于更新
- Web应用程序-动态图像渲染
- 如何在为单页应用程序动态加载新的 innerHTML 时清除 DOM 变量和存储
- 使用帐户为流星应用程序动态生成的用户名