HowlerJS step 函数不会在搜索时更新范围输入值

HowlerJS step function doesn't update range input value on seek

我正在使用 Howler.js 创建播客播放器。

我有 4 个按钮和一个用于控制播客的输入。

当您点击播放、后退和前进按钮时,在执行它们的操作后,它们会调用一个名为 step 的函数,该函数负责更新范围输入的值。

  function step(){
    var self = this;

    var seek = sound.seek() || 0;
    rangeInput.attr('value', seek);

    //If sound is still playing, continue stepping
    if(sound.playing()){
      requestAnimationFrame(step.bind(self));
    }

  }

当您尝试使用输入更改您在播客中的位置时,问题就来了。虽然它确实向前移动了音频,但 step 函数停止更新范围输入的值。

奇怪的是,如果您在使用范围输入后检查元素,您确实可以看到它的值正在 DOM 中更新。但是那个点再也没有移动过。

我创建了一个 fiddle 来重现这个问题。 Link to Fiddle

这是我的全部代码

var sound = new Howl({
    src: ['https://s3.amazonaws.com/ShopTalk/080_rapidfire_19.mp3'],
    onplay:function(){
      requestAnimationFrame(step.bind(this));
    }
  });

  var rangeInput = $('#range');

  sound.once('load', function(){
    $('#loading').hide();
    $('#ready').show();
    $('#controls').show();
    $('#range').attr('max', sound.duration());
    console.log('Podcast Loaded');
  });

  $('#play').on('click', playPodcast);
  $('#pause').on('click', pausePodcast);
  $('#skip-back').on('click', skipBackward);
  $('#skip-forward').on('click', skipForward);
  rangeInput.change(seek);

  function step(){
    var self = this;

    var seek = sound.seek() || 0;
    rangeInput.attr('value', seek);

    //If sound is still playing, continue stepping
    if(sound.playing()){
      requestAnimationFrame(step.bind(self));
    }

  }

  function seek(){

    var seekedTime = $('#range').val();
    sound.seek([seekedTime]);

    step();
  }

  function playPodcast(){
    sound.play();
  }

  function pausePodcast(){
    sound.pause();
  }

  function skipForward(){
    sound.seek([sound.seek() + 5]);
    step();
  }

  function skipBackward(){
    sound.seek([sound.seek() - 5]);
    step();
  }

总而言之,

我正在使用一个名为 step() 的函数,只要音频文件仍在播放,它就会不断更新范围输入的值。当您使用范围输入手动 select 播客中的某个位置时,它会停止更新该值,即使它正在 DOM 中更新,并且播客会准确地寻找其新位置并继续播放。

我发现了一个错误。
错误是多重播放 mp3。
您可以防止玩多个。

添加此代码。

  function playPodcast(){
    if(sound.playing()) {
      return;
    }

    sound.play();
  }

这就是您问题的答案。

  function seek() {
    var seekedTime = $('#range').val();
    sound.pause();
    sound.seek([seekedTime]);
    sound.play();
  }

测试是https://jsfiddle.net/h6b57f4v/5/

[参考]https://github.com/goldfire/howler.js/issues/1156#issuecomment-487292193

我认为有多个错误,所以我尝试了不同的逻辑来更好地工作。

基本上阻止多个 sound.play() 播放,前进和后退。

阻止 rangeInput 在我们试图拖动它时进行设置。

所以不要绑定requestAnimationFrame(step)如果鼠标在rangeInput

Js fiddle sample

var self = this;
var mousehover = false;


var sound = new Howl({
  src: ['https://s3.amazonaws.com/ShopTalk/080_rapidfire_19.mp3'],
  onplay: function() {
    id = requestAnimationFrame(step);
  }
});

var rangeInput = $('#range');

sound.once('load', function() {
  $('#loading').hide();
  $('#ready').show();
  $('#controls').show();
  $('#range').attr('max', sound.duration());
  console.log('Podcast Loaded');
});

$('#play').on('click', playPodcast);
$('#pause').on('click', pausePodcast);
$('#skip-back').on('click', skipBackward);
$('#skip-forward').on('click', skipForward);
rangeInput.change(seek);
rangeInput.on("mouseenter", () => {
  mousehover = true;
})
rangeInput.on("mouseout", () => {
  mousehover = false;
  step();
})


function step() {
  var seek = sound.seek() || 0;
  rangeInput.val(seek);
  //If sound is still playing, continue stepping
  if (!mousehover && sound.playing()) {
    id = requestAnimationFrame(step);
  }

}



function seek() {

  cancelAnimationFrame(id)
  var seekedTime = $('#range').val();
  sound.seek([seekedTime]);
  sound.play()
}

function playPodcast() {
  if (!sound.playing())
    sound.play();
}

function pausePodcast() {
  if (sound.playing())
    sound.pause();
}

function skipForward() {
  sound.seek([sound.seek() + 5]);
  if (!sound.playing())
    sound.play();
}

function skipBackward() {
  sound.seek([sound.seek() - 5]);
  if (!sound.playing())
    sound.play()
}
body {
  padding: 25px;
}

#ready {
  display: none;
}

#controls {
  display: none;
}

#range {
  -webkit-appearance: none;
  margin-top: 35px;
  width: 100%;
  height: 15px;
  border-radius: 5px;
  background: #d3d3d3;
  outline: none;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
}

#range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #00AEC7;
  cursor: pointer;
}

#range::-moz-range-thumb {
  width: 25px;
  height: 25px;
  border-radius: 50%;
  background: #00AEC7;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/howler/2.1.2/howler.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script>
<p id="loading">Loading...</p>
<p id="ready">Ready</p>
<hr />
<div id="controls">
  <button id="play">Play</button>
  <button id="pause">Pause</button>
  <button id="skip-back">Back 5 seconds</button>
  <button id="skip-forward">Forward 5 seconds</button>
  <br />
  <input type="range" min="0" max="" value="0" id="range">
</div>