我正在努力整合一个音频功能,用于一个简单的脚本来播放钢琴上的音符。我对音频标签无法处理新请求直到播放完毕的解决方案是为每次后续点击创建一个新的音频元素,然后设置一个侦听器,以便在播放其声音后删除该元素。它工作得很好,除了看起来我的事件监听器被覆盖,因此只跟随声音的最后一次迭代,留下许多音频元素保持完整和无效。
代码:
var x = 0;
function playSound(){
x = x + 1;
var na = document.createElement('audio');
na.setAttribute('id','cycle'+x);
document.body.appendChild(na);
var ta = document.getElementById('cycle'+x);
var ns = document.createElement('source');
ns.setAttribute('src','notify.wav');
ta.appendChild(ns);
document.getElementById('cycle'+x).addEventListener('ended', function(){
document.body.removeChild(document.getElementById('cycle'+x));
try{document.getElementById('cycle'+x).remove();}
catch(err){}});
ta.play();
}
并将声音预加载到页面中:
<audio id="preloader" preload="auto"><source src="notify.wav"></source></audio>
我想为每个生成的音频元素设置单独的事件侦听器,以便在播放文件时删除该元素。
答案 0 :(得分:1)
您的问题源于引用问题 - 通过示例代码中使用的方法,您无法在侦听器中获取当前作用域中的所需元素。
Safari的控制台告诉我:
[Error] NotFoundError: DOM Exception 8: An attempt was made to reference a Node in a context where it does not exist.
(anonymous function) (_display, line 33)
显然,所有事件侦听器都正确触发。
当然,你可以进行大规模的搜寻,找到背后的真正原因,但既然你正在寻找解决问题的方法,那么应该这样做:
删除以下行:
document.body.removeChild(document.getElementById('cycle'+x));
try{document.getElementById('cycle'+x).remove();}
catch(err){}});
并将其替换为:
this.remove();
事件侦听器回调将始终提供相关元素this
。这是获得有效参考资料的最安全途径。