javascript - 使用JQueryUI作为音频搜索控件,并在更改歌曲时将新的 slider 重新绑定(bind)到相同的<audio>控件

标签 javascript jquery html5 jquery-ui html5-audio

谢谢你看我的问题。小提琴HERE
我正在尝试为一页上的许多歌曲实现音频播放器。这是使用JQueryUI滑块和HTML5音频,一个音频元素和多个滑块。
现在的问题是:
滑块不与音频一起设置动画。
滑块不搜索音频。
以前,当以上两个都工作时,一旦您在歌曲中选择了一个位置,滑块将不再设置动画。
我已经创建了一个函数来在单击新歌时rebindSlider()。在这个函数中,发生了两件事:a)创建了新的滑块,定义了slide和stop监听器;b)将新的滑块绑定到新歌音频元素上的timeupdate事件。我觉得这应该是我所需要的,但滑块不绑定,当您试图拖动滑块时会看到一个undefined错误。
使用一个滑动条和一个音频元素,我已经实现了90%的效果;不过,当我为滑动条引入多个div时,问题就开始出现了。
以下是rebindSlider的代码:

function rebindSlider(sliderDiv) {
  var createSeek = function() {
    sliderDiv.slider({
      value: 0,
      step: 1,
      orientation: "horizontal",
      range: "min",
      max: audioPlayer.duration,
      animate: true,

      slide: function() {
        manualSeek = true;
      },

      stop: function(e, ui) {
        manualSeek = false;
        audioPlayer.currentTime = ui.value;
      }
    });
  };

  createSeek();

  $(audioPlayer).bind('timeupdate', function() {
    if (!manualSeek) {
      sliderDiv.slider('value', audioPlayer.currentTime);
    }
  });
} 

下面是进一步的描述。
页面上有一个歌曲列表。每首歌都有一个包含div,其中有一个<a>包含元数据(小提琴中没有),还有一个为音频搜索滑块指定的div。页面上只有一个音频元素,当您单击歌曲时,该元素的源代码将被重新加载。
单击歌曲时,我想销毁绑定到播放音频的滑块(如果需要),并将单击的歌曲的新滑块绑定到音频播放器。
我得到的最接近的结果是让滑块1)在歌曲播放时开始设置动画2)将滑块拖动到歌曲中的不同位置。但一旦滑块移动,它就不再设置动画。重构之后,滑块不再工作,尽管我可以去之前的提交获取工作代码,但重构非常激烈,我宁愿呈现当前的非工作代码,因为它更好地表示了我希望得到的结果。
推理和附加信息。
我正在制作一个网络应用,我有一个音频播放器的概念,我宁愿建立自己,而不是修改我遇到的任何东西。也就是说,如果你知道我可以实施的东西,我会喜欢建议。
这个想法听起来很简单,而且大部分都已经完成了,但是有一个非常关键的部分我遇到了麻烦,那就是设置滑动条来设置动画,并在音频轨迹中寻找所需的位置,并且能够在单击歌曲时将新的滑动条重新绑定到音频。

最佳答案

要使滑块正常工作,需要进行一些更改。为了申请,我将把每一项都包括在内。
无效的滑块最大值
第一个问题是滑块的最大值设置为audioPlayer.duration,这通常都是好的,除了HTML5音频播放器异步加载音频资源。这意味着,即使您可能在设置滑块之前加载了音频,但音频资源可能尚未加载,并且audioPlayer.duration可能无效(可能NaN)。
只需将max键(和值)从滑块初始化中移除,这将起作用。还有维奥拉!滑块移动!
一个警告:滑块的默认最大值为100个单位,音频的持续时间略高于25秒,因此当滑块在播放过程中的1/4时,歌曲将结束播放。我们可以将max键设置为25(秒),但这有点不雅,如果我们将音频更改为使用不同的源,则不会起作用。
设置滑块最大值
一旦异步加载完成,就必须在处理事件时捕获audioPlayer.duration。Javascript提供了这样一个事件:onloadedmetadata。让我们安装一个事件处理程序,并使其正常工作:

audioPlayer.onloadedmetadata = function() {
    $(".slider").slider("option", { max: Math.floor(audioPlayer.duration) });
};

现在,只要加载了音频资源,就可以将滑块的max设置为audioPlayer.duration。实际上,这是当前为所有滑块设置的最大值,但这不应该是个问题,因为它们都是隐藏的。如果您有大量歌曲,可能会有一点延迟,您可能希望找到要更新的特定滑块。
平滑滑动
现在,您可能会注意到在这些更改之后,滑块有点跳跃。它先暂停一秒钟,然后跳跃,然后暂停,等等。通过在滑块初始化中将step键更改为0.1可以非常容易地解决这个问题,如下所示:
sliderDiv.slider({
  value: 0,
  step: 0.1,
  orientation: "horizontal",

时间更新每50到250毫秒发生一次,但滑块只能以1秒为增量移动。现在,以1/10秒的增量,滑块将更平稳地移动。如果你愿意的话,你可以稍微减少一点,但不要把数字太小;0.01是实际的下限。
更新播放结束状态
当歌曲结束时,“播放”按钮将保持播放状态,即使不再播放任何内容。这也有一个活动:onended。我们将使用该事件更新UI,这样用户就不会感到困惑:
audioPlayer.onended = function() {
  playButton.removeClass('fa-pause-circle-o');
  playButton.addClass('fa-play-circle-o');
};

现在,当歌曲结束时,“播放”按钮将返回到“播放”状态,用户将知道单击它将播放歌曲。
重构播放按钮状态
因为现在有3个地方可以更新Play按钮的状态,这涉及到复制,所以我们可以重构状态处理。此功能将最终设置播放按钮的状态:
function setUIState() {
  if (audioPlayer.paused || audioPlayer.ended) {
    playButton.removeClass('fa-pause-circle-o');
    playButton.addClass('fa-play-circle-o');
  } else {
    playButton.removeClass('fa-play-circle-o');
    playButton.addClass('fa-pause-circle-o');
  }
}

现在,从其他函数调用它,您将得到onended事件处理程序:
audioPlayer.onended = function() {
  setUIState();
};

changeUI函数:
function changeUI(selectedSong) {
  setUIState();

  var sliderDiv = selectedSong.parent().find('.slider');
  rebindSlider(sliderDiv);//Bind the desired slider
  $('.slider').hide(); //Hide all sliders
  sliderDiv.show();//Show only the desired slider
} 

并且,播放按钮单击处理程序:
$(".playButton").click(function() {    
  if (audioLoaded === true) {
    if (!audioPlayer.paused) {
      audioPlayer.pause();
    } else {
      audioPlayer.play();
    }
    setUIState();
  } else {
    alert("Please click a song");
  }
  return false;
});

这使得按钮的UI状态管理非常容易处理,并防止状态在应用程序中蔓延。您已经可以看到重构后的代码是如何明显地更加清晰,并且更易于维护的。另外,作为奖励,我们必须使用coolaudioPlayer.ended属性,您看不到它使用得太多。
但是等等,还有更多!
有了以上的变化,你就可以拥有一个非常实用的音频播放器。但这肯定不是特性功能的终点。总有成长的空间!
我已经创建了一个jsFiddle,其中包括所有这些更改,以及对原始代码的一些其他mod。您可以在:https://jsfiddle.net/mgaskill/mp087adp/找到最新版本。附加功能可能会不断出现,但是jsFiddle已经包含了这些附加功能:
音量控制(滑块)
时间显示器
为音频控件动态生成的HTML(使HTML更简单)

关于javascript - 使用JQueryUI作为音频搜索控件,并在更改歌曲时将新的 slider 重新绑定(bind)到相同的<audio>控件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37501717/

相关文章:

html - 图像 slider 过度滚动

css - 占位符文本在Safari中的textarea中用完了吗?

javascript - 使用开/关事件绑定(bind)?

javascript - 通过 Ajax 上传文件是重复的

javascript - 导出默认 { name } 和命名导出 { name } 之间的区别

javascript - 大小以适合 Canvas 上的字体

javascript - 使用空白值初始化 React 数字输入控件?

javascript - 下拉+用户输入(文本)

不使用 jQuery 的 JavaScript 事件注册

javascript - 将鼠标坐标转换为HTML5 Canvas转换后上下文的最佳方法