【问题标题】:Javascript audio layering eventListener HTML5 fails on multiple iterationsJavascript 音频分层 eventListener HTML5 在多次迭代中失败
【发布时间】:2013-12-13 23:17:11
【问题描述】:

我正在努力整合一个音频功能,以便在一个简单的脚本上使用,以像钢琴上的音符一样弹奏音符。我对音频标签在播放之前无法处理新请求的解决方案是为每次后续点击创建一个新的音频元素,然后设置一个侦听器以在播放完声音后删除该元素。它工作得很好,只是我的事件监听器似乎被覆盖了,所以只跟随声音的最后一次迭代,使许多音频元素完好无损且处于非活动状态。

代码:

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>

我希望为每个生成的音频元素设置单独的事件侦听器,以便在播放文件时删除该元素。

【问题讨论】:

  • 看起来不错。您确定问题源于被覆盖的事件侦听器吗?鉴于上面的代码,它似乎没有多大意义。
  • 我只能假设是这种情况,因为当我查看创建的元素时,快速点击 10 次,所有元素都会播放,但只有最后一个会服从 remove();在页面上留下 9 个非活动元素。
  • 您是否尝试过将err 的内容打印到控制台,一旦catch() 发挥作用(我认为它在某些时候会起作用)?
  • 没有错误记录,至少在 Chrome31 中是这样。 Firefox 为 getElementById() 记录了一个空值,但我认为这是因为它在完成 removeChild() 之后尝试删除()。这样做是为了防止 ipad 出错。

标签: javascript html


【解决方案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。这是您获得有效参考的最安全途径。

【讨论】:

  • 现在完美运行。这一下子解决了这两个问题。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-11
  • 2021-12-14
  • 1970-01-01
  • 1970-01-01
  • 2012-06-14
  • 2013-11-11
  • 2014-07-17
相关资源
最近更新 更多