当以编程方式修改当前时间时,音频播放按钮会发出幻像第二次单击,从而阻止播放

问题描述 投票:0回答:1

当我暂停音频并将其设置为当前时间时,它会执行一些奇怪的操作。当我按下控制音频

.paused
状态的按钮时,它似乎会自动再次单击,从而阻止音频播放。为什么?

此外,如果我再次设置 currentTime,它会决定停止单击播放按钮两次。每次我设置 currentTime 时都会发生这种情况。可以用这段代码来演示。 (音频变慢只是因为示例音频太短)。

<!doctype html><html><body>
  <button id="play" disabled>play</button>
  <button id="idk">load audio</button>
  <script>
    var clicks = 0; console.clear();
    idk = document.getElementById("idk");
    idk.addEventListener("click", async ()=>{
      aud = new Audio("https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3")
      aud.addEventListener('canplaythrough', init);
    }, {once: true});
    function init(){
      /**/aud.playbackRate = 0.25;//only to lengthen the audio to give you time.
      playButton = document.getElementById("play");
      playButton.disabled = false;
      idk.innerText = "pause and set time to 1";
      playButton.addEventListener("click", e=>{
        if(aud.paused){
          aud.play();
          playButton.innerText = "pause";
        }else{
          aud.pause();
          playButton.innerText = "play";
        }
        //Nothing different between duplicate click events, logging it takes up space
        console.log(clicks++, aud.paused, /*e*/);//clicks++ to tell apart logs.
      });
      idk.addEventListener("click", e=>{
        console.log("Rightmost element clicked");
        if(!aud.paused){ aud.pause(); playButton.innerText = "play"; }
        aud.currentTime = 1;
      });
    }
  </script>
</body></html>

查看实例(由于控制台污染而删除了事件日志记录)

只需单击

load audio
,然后在获得许可后单击
play
,最后单击
pause and set time to 1

此后,每次实际点击都会触发点击事件两次(如日志中所示),从而阻止音频播放。解决此问题的唯一方法是再次单击

pause and set time to 1
,然后尝试单击
play
。你会成功,但如果你再次点击右键,你将再次面临这个问题。

我还注意到,稍微修改一下,双击就会变成四击,仍然会导致问题,因为四次点击是偶数。

<!doctype html><html><body>
  <button id="play">play</button>
  Control+Click to pause the audio and change it's currentTime value
  <script>
    var clicks = 0; console.clear();    
    playButton = document.getElementById("play");
    playButton.addEventListener("click", async ()=>{
      /**/window.aud = new Audio("https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3");
      aud.addEventListener('canplaythrough', ()=>{
        playButton.style.color = "#080";
        /**/aud.playbackRate = 0.25;//only to lengthen the audio to give you time.
        playButton.addEventListener("click", e=>{
          if(e.ctrlKey){
            if(!aud.paused){ aud.pause(); playButton.innerText = "play"; }
            aud.currentTime = 1;
            return;
          }
          if(aud.paused){
            aud.play();
            playButton.innerText = "pause";
          }else{
            aud.pause();
            playButton.innerText = "play";
          }
          //Nothing different between duplicate click events, logging it takes up space
          console.log(clicks++, aud.paused, /*e*/);//clicks++ to tell apart logs.
        });
      });
    }, {once: true});
  </script>
</body></html>

查看实例(由于控制台污染而删除了事件日志记录)

要使用第二个示例,请使用 CTRL+Click 作为

pause and set time to 1
按钮。

在这两个示例中,在控制台中运行

aud.play();
似乎可以工作,但仍然不允许播放/暂停按钮起作用并双击它们。在控制台中设置
aud.currentTime
(设置偶数次后)没有效果,连续两次设置代码
aud.currentTime
也没有效果。用户必须单击它,然后再次单击它。

这种情况发生在 ChromeOS 上的 Chrome Beta 127.0.6533.94 以及 Android 14 上的 Chrome 127.0.6533.85 和 Firefox 129.0 上。我根本无法让它在非欧盟 iOS 上运行。

但是...

MacOS Sonoma 上的 Safari 17.3(通过 Browserling,如果有任何差异)似乎可以按预期工作。

提前抱歉,如果测试不够,或者我犯了一个非常明显的错误

javascript html onclick html5-audio
1个回答
0
投票

要解决您的问题,您需要考虑以下几点:

  1. 事件监听器复制:每次单击

    play
    按钮时,都会添加一个新的事件监听器。这可能会导致触发多个事件侦听器,从而导致双击行为。要解决此问题,确保事件侦听器仅添加一次

  2. 浏览器差异:不同的浏览器(例如 Google Chrome)以不同的方式处理

    currentTime
    属性,如 在此 StackOverflow 问题MDN 文档:BaseAudioContext:currentTime 属性中所述。

在本例中,您的问题是由于事件重复,您在

click
按钮上多次触发了
play
事件。这是代码:

<!doctype html>
<html>
<body>
  <button id="play" disabled>play</button>
  <button id="idk">load audio</button>
  <script>
    var clicks = 0;
    console.clear();
    idk = document.getElementById("idk");
    idk.addEventListener("click", async () => {
      aud = new Audio("https://interactive-examples.mdn.mozilla.net/media/cc0-audio/t-rex-roar.mp3");
      aud.addEventListener('canplaythrough', init, { once: true });
    }, { once: true });

    function init() {
      aud.playbackRate = 0.25; // only to lengthen the audio to give you time.
      playButton = document.getElementById("play");
      playButton.disabled = false;
      idk.innerText = "pause and set time to 1";

      playButton.addEventListener("click", togglePlayPause, { once: true });
      idk.addEventListener("click", setTimeToOne, { once: true });
    }

    function togglePlayPause() {
      if (aud.paused) {
        aud.play();
        playButton.innerText = "pause";
      } else {
        aud.pause();
        playButton.innerText = "play";
      }
      console.log(clicks++, aud.paused);
      playButton.addEventListener("click", togglePlayPause, { once: true });
    }

    function setTimeToOne() {
      console.log("Rightmost element clicked");
      if (!aud.paused) {
        aud.pause();
        playButton.innerText = "play";
      }
      aud.currentTime = 1;
      idk.addEventListener("click", setTimeToOne, { once: true });
    }
  </script>
</body>
</html>

这可确保每次点击仅调用一次

togglePlayPause
函数,从而防止出现多事件侦听器问题。

© www.soinside.com 2019 - 2024. All rights reserved.