简单音频播放器的多个实例

时间:2018-03-17 00:39:57

标签: javascript audio

我一直在玩这个代码用于简单的音频播放器,但我注意到它只允许页面上的一个玩家(第二个按钮不起作用)。它确实使用类而不是id,但是使用querySelector可能是一个问题。理想情况下,我想在页面上有几个,所以想知道我将如何使用这种编码方式(即使用没有JQuery的字体很棒)。

<audio src="http://bornemark.se/bb/mp3_demos/PoA_Sorlin_-_Stay_Up.mp3" class="sound" loop></audio>
<a href="#" class="button"><i class="fa fa-play" aria-hidden="true"></i></a> <br>

<audio src="http://bornemark.se/bb/mp3_demos/PoA_Sorlin_-_Stay_Up.mp3" class="sound" loop></audio>
<a href="#" class="button"><i class="fa fa-play" aria-hidden="true"></i></a>

    <script>
      document.querySelector(`.button`).addEventListener(`click`, event => {
      let icon = document.querySelector(`.button i`); 
      let sound = document.querySelector(`.sound`);

      icon.classList.toggle(`fa-pause`);
      icon.classList.toggle(`fa-play`);

       if (icon.classList.contains(`fa-pause`)) {
        sound.play();
        } 
      else {
        sound.pause();
      }
    });
    </script>

2 个答案:

答案 0 :(得分:1)

我认为主要问题是querySelector,因为这只会得到.sound的第一个实例。 querySelectorAll将返回所有.sound元素的数组,但这也不起作用。它根本不会发挥任何作用。

我建议你继续使用其他建议在按钮上使用ID和数据属性,该按钮引用音频目标的ID,因此它知道要绑定到哪个音频元素。这样的事情应该有效:

<audio id="audio-1" src="address/of/file" loop></audio>
<i data-audio-target="audio-1" class="audio-button fa fa-play"></i><br/>

<audio id="audio-2" src="address/of/file" loop></audio>
<i data-audio-target="audio-2" class="audio-button fa fa-play"></i>

<script>
  document.addEventListener('click', event => {

    // Do nothing if the target was not an .audio-button
    if (!event.target.classList.contains('audio-button'))
      return false;

    // If the target was an .audio-button
    let button = event.target;
    let audioTarget = button.getAttribute('data-audio-target'); // Gets the ID of the audio element that you want to start
    let sound = document.getElementById(audioTarget);

    button.classList.toggle(`fa-pause`);
    button.classList.toggle(`fa-play`);

    if (button.classList.contains(`fa-pause`)) {
      sound.play();
    } 
    else {
      sound.pause();
    }
  });
</script>

答案 1 :(得分:1)

移除<a>并将<i>包裹在<audio>标记周围。这听起来很奇怪,但像<a><audio>这样的互动元素更容易与像<i>这样的定相元素挂钩。详细信息在演示中进行了评论。

顺便说一下,播放视频或音频时可能会出错,而Promises则会出错。我已经添加了针对该错误的修复程序,并且可能必须在页面上有音频/视频时使用它。这不是一个错误,它是一个功能。 See this article for details

演示

i {
  display: block;
  padding: 3px 5px;
  cursor: pointer;
  line-height: 1.4;
  width: 99%;
  background: linear-gradient(#88C1FF, #3E7EBD, #88C1FF);
  box-shadow: -3px 3px 5px 3px rgba(0, 0, 0, 0.6);
  ;
}

i:hover {
  color: rgba(255, 255, 0, 0.8);
  text-shadow: 2px 1px 1px rgba(0, 0, 0, 0.6);
  background: rgb(62, 126, 189);
  transition: 0.7s
}

hr {
  margin: 20px auto;
}


/* These rules will display the [title] attribute value as text content */

i::after {
  font: 700 16px/1 Verdana;
  font-variant: small-caps;
  content: '\a0\a0'attr(title)
}


/* For Demo only */

.as-console-wrapper {
  width: 100px;
  margin-left: 80%;
}
<!DOCTYPE html>
<html>

<head>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
</head>

<body>


  <main>

    <i class="fa fa-play" aria-hidden="true" title="Scarface: Balls">
    <audio src="https://storage04.dropshots.com/photos7000/photos/1381926/20180317/124345.mp4" class="sound" loop></audio>
    </i>
    <br>
    <hr>

    <i class="fa fa-play" aria-hidden="true" title="Vader: CNN">
    <audio src="https://storage04.dropshots.com/photos7000/photos/1381926/20180317/124344.mp4" class="sound" loop></audio>
    </i>
    <br>
    <hr>

    <i class="fa fa-play" aria-hidden="true" title="Man of Mystery: Behave">
    <audio src="https://storage04.dropshots.com/photos7000/photos/1381926/20180317/124343.mp4" class="sound" loop></audio>
    </i>
    <br>
    <hr>

    <i class="fa fa-play" aria-hidden="true" title="Ren: Magic Nose Goblins">
    <audio src="https://storage04.dropshots.com/photos7000/photos/1381926/20180317/124342.mp4" class="sound" loop></audio>
    </i>
    <br>
    <hr>
    <i class="fa fa-play" aria-hidden="true" title="Jerky: Whatnot">
    <audio src="https://storage04.dropshots.com/photos7000/photos/1381926/20171228/181810.mp4" class="sound" loop></audio>
    </i>
    <br>

    <hr>

    <i class="fa fa-play" aria-hidden="true" title="Samuel L. Jackson: Righteous">
    <audio src="https://storage04.dropshots.com/photos7000/photos/1381926/20171228/181811.mp4" class="sound" loop></audio>
    </i>
    <br>

  </main>
  <script>
    // Collect all <i> into a NodeList then convert it into an array
    const I = Array.from(document.querySelectorAll('i'));

    // Run each <i> in a loop and bind a click event to it--callback is player()
    I.forEach(function(a) {

      a.onclick = player;

    });

    function player(event) {

      // Reference the clicked <i>
      var tgt = event.target;

      // Reference the <audio> inside <i>
      var mp3 = tgt.querySelector('audio.sound');

      // if <i> has class .fa-play...
      if (tgt.classList.contains('fa-play')) {

        // play the mp3...
        mp3.play();

        // ...otherwise...
      } else {

        // pause the mp3...
        mp3.pause();

      }

      // toggle icons
      tgt.classList.toggle('fa-play');
      tgt.classList.toggle('fa-pause');

    }

    /* HTMLMediaElement.play() Returns a Promise
    || If you ever receive errors about Promises, 
    || use the following to handle Promises.
    */
    var promise = document.querySelector('audio').play();
    promise.then(_ => {
      document.querySelector('audio').pause();
      document.querySelector('audio').currentTime = '0';
      console.log('Promise Resolved');
    }).catch(error => {
      return;
    });
  </script>
</body>

</html>