一个页面上的多个音频播放器,只有第一个播放器响应点击

Multiple Audio Players on one page, only first player responds to click

我从 this 文章中获取了音频播放器代码,进行了一些样式更改,现在正尝试在一个页面上显示多个此类播放器。目前,只有第一个玩家响应点击。

我使用行和列元素来显示整页行,每行 3 个播放器,每个播放器都有自己的图标图像和音频源文件。我现在的麻烦是建立索引搜索程序,以便在单击button_X时JS可以播放audio_X。

我已经在 Whosebug 上尝试了其他解决方案,但无济于事,所以我删除了我尝试过的所有更改,并从头开始。

const playerButton = document.querySelector('.player-button'),
  audio = document.querySelector('audio'),
  playIcon = `
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
        <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
      </svg>
          `,
  pauseIcon = `
            <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
      <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
    </svg>
          `;

function toggleAudio() {
  if (audio.paused) {
    audio.play();
    playerButton.innerHTML = pauseIcon;
    //  document.getElementById("1").style.opacity = "1";
  } else {
    audio.pause();
    playerButton.innerHTML = playIcon;
    //      document.getElementById("1").style.opacity = "0";

  }
}
playerButton.addEventListener('click', toggleAudio);

function audioEnded() {
  playerButton.innerHTML = playIcon;
}

audio.onended = audioEnded;

const timeline = document.querySelector('.timeline');


function changeTimelinePosition() {
  const percentagePosition = (100 * audio.currentTime) / audio.duration;
  timeline.style.backgroundSize = `${percentagePosition}% 100%`;
  timeline.value = percentagePosition;
}

audio.ontimeupdate = changeTimelinePosition;

function changeSeek() {
  const time = (timeline.value * audio.duration) / 100;
  audio.currentTime = time;
}

timeline.addEventListener('change', changeSeek);


const soundButton = document.querySelector('.sound-button'),
  soundIcon = `
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
      <path fill-rule="evenodd" d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM14.657 2.929a1 1 0 011.414 0A9.972 9.972 0 0119 10a9.972 9.972 0 01-2.929 7.071 1 1 0 01-1.414-1.414A7.971 7.971 0 0017 10c0-2.21-.894-4.208-2.343-5.657a1 1 0 010-1.414zm-2.829 2.828a1 1 0 011.415 0A5.983 5.983 0 0115 10a5.984 5.984 0 01-1.757 4.243 1 1 0 01-1.415-1.415A3.984 3.984 0 0013 10a3.983 3.983 0 00-1.172-2.828 1 1 0 010-1.415z" clip-rule="evenodd" />
    </svg>`,
  muteIcon = `
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
      <path fill-rule="evenodd" d="M9.383 3.076A1 1 0 0110 4v12a1 1 0 01-1.707.707L4.586 13H2a1 1 0 01-1-1V8a1 1 0 011-1h2.586l3.707-3.707a1 1 0 011.09-.217zM12.293 7.293a1 1 0 011.414 0L15 8.586l1.293-1.293a1 1 0 111.414 1.414L16.414 10l1.293 1.293a1 1 0 01-1.414 1.414L15 11.414l-1.293 1.293a1 1 0 01-1.414-1.414L13.586 10l-1.293-1.293a1 1 0 010-1.414z" clip-rule="evenodd" />
    </svg>`;

function toggleSound() {
  audio.muted = !audio.muted;
  soundButton.innerHTML = audio.muted ? muteIcon : soundIcon;
}

soundButton.addEventListener('click', toggleSound);
<div class="audio-player left">

  <div class="icon-container">

    <img src="coverart1.jpg" style="width: 100%" alt="">
    <!--<svg xmlns="http://www.w3.org/2000/svg" class="audio-icon" viewBox="0 0 20 20" fill="currentColor">
             <path d="blahblahblahpath" />
        </svg>-->
    <audio src="audio/1.mp3"></audio>
  </div>
  <div class="controls">
    <button class="player-button">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
      <path fill-rule="evenodd" d="blahblahblahpath" />
    </svg>
        </button>
    <input type="range" class="timeline" max="100" value="0">
    <button class="sound-button">
          <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="#3D3132">
      <path fill-rule="evenodd" d="blahblahblahpath" clip-rule="evenodd" />
    </svg>
        </button>
  </div>
</div>

有了这个结构,我不太确定如何为特定玩家index/search(除了知道我应该使用 queryselectALL 并为某些 JS 函数添加 for 循环之外)。

任何修复?目前第一个播放器运行良好,但没有其他播放器响应点击。也许与事件侦听器有关?

beyond knowing that i should probably use queryselectALL and add for loops to some JS functions

这就是重点:您需要为每个播放器实例分配事件侦听器。

let audioPlayers = document.querySelectorAll(".audio-player");

if (audioPlayers.length) {
  audioPlayers.forEach(function(audioPlayer, i) {
    let audio = audioPlayer.querySelector("audio");
    let playerButton = audioPlayer.querySelector(".player-button");
    playerButton.addEventListener("click", function(e) {
      let current = e.currentTarget;
      let audio = current.closest(".audio-player").querySelector("audio");
      let btnSvg = current.querySelector(".useBtn");
      if (!audio.paused) {
        btnSvg.setAttribute("href", "#icon-play");
        audio.pause();
      } else {
        btnSvg.setAttribute("href", "#icon-pause");
        audio.play();
      }
    });

    let timeline = audioPlayer.querySelector('.timeline');
    timeline.addEventListener('change', function(e) {
      let time = (timeline.value * audio.duration) / 100;
      audio.currentTime = time;
    });

    audio.addEventListener('ended', function(e) {
      console.log('audio finished');
      timeline.value = 0;
    });

    audio.addEventListener('timeupdate', function(e) {
      let percentagePosition = (100 * audio.currentTime) / audio.duration;
      timeline.value = percentagePosition;
    });
  });
}
svg {
  display: block;
  width: 1em;
}

.player-button {
  display: inline-block;
  height: 1em;
  background: none;
  padding: 0;
  border: none;
  font-size: 1.2em;
  position: relative;
  bottom: -0.15em;
}
<div class="audio-player left">
  <div class="icon-container">
    <audio preload="metadata" src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3"></audio>
  </div>
  <div class="controls">
    <button class="player-button">
      <svg viewBox="0 0 20 20" fill="#3D3132">
        <use class="useBtn" href="#icon-play" />
      </svg>
    </button>
    <input type="range" class="timeline" min="0" max="100" step="1" value="0">
  </div>
</div>

<div class="audio-player left">
  <div class="icon-container">
    <audio preload="metadata" src="https://cdn.plyr.io/static/demo/Kishi_Bashi_-_It_All_Began_With_a_Burst.mp3"></audio>
  </div>
  <div class="controls">
    <button class="player-button">
      <svg viewBox="0 0 20 20" fill="#3D3132">
        <use class="useBtn" href="#icon-play" />
      </svg>
    </button>
    <input type="range" class="timeline" min="0" max="100" step="1" value="0">
  </div>
</div>

<svg class="plyrBtns" style="display:none" aria-hidden="true">
  <symbol class="icon icon-play" id="icon-play" viewBox="0 0 20 20">
    <path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM9.555 7.168A1 1 0 008 8v4a1 1 0 001.555.832l3-2a1 1 0 000-1.664l-3-2z" clip-rule="evenodd" />
  </symbol>
  <symbol class="icon icon-pause" id="icon-pause" viewBox="0 0 20 20">
    <path fill-rule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zM7 8a1 1 0 012 0v4a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v4a1 1 0 102 0V8a1 1 0 00-1-1z" clip-rule="evenodd" />
  </symbol>
</svg>