user12625952
user12625952

Reputation:

Ability to play various sound files from divs on website

I am in the process of creating my own music player on the website. I have a problem that I don't know what to do so that I can play a few different songs from different divs. To be more specific, I mean that when you press the button.play, in the first .audio-player will play music.mp3. And after pressing the button. play in the second .audio-player will play music1.mp3. Code below.

<div class="audio-player">
        <audio src="music.mp3"></audio>
        <button class="play">play</button>
        <div class="seek-bar">
            <div class="fill"><div class="handle"></div></div>
        </div>
    </div>
    <div class="audio-player">
        <audio src="music1.mp3"></audio>
        <button class="play">play</button>
        <div class="seek-bar">
            <div class="fill"><div class="handle"></div></div>
        </div>
    </div>
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body {
    background: #0f0f0f;
    color: #fff;
    height: 100vh;
    display: flex;
    justify-content: center;
    align-items: center;
    touch-action: none;
}
.audio-player {
    width: 80%;
    height: 200px;
    box-shadow: 0 0 10px rgba(255,255,255,.2);
    border-radius: 10px;
}
.play {
    width: 40px;
    height: 40px;
    background-color: #fff;
    border-radius: 50%;
    margin-bottom: 30px;
    outline: none;
    border: none;
}
.play:focus {
    background-color: #f90;
}
.seek-bar {
    width: 90%;
    margin: 0 auto;
    height: 4px;
    border-radius: 4px;
    background-color: rgba(255,255,255,.2);
    display: flex;
    align-items: center;
    cursor: pointer;
}
.fill {
    height: 4px;
    border-radius: 4px;
    background-color: #fff;
    position: relative;
}
.handle {
    width: 12px;
    height: 12px;
    border-radius: 50%;
    position: absolute;
    right: 0;
    top: 50%;
    background: #fff;
    transform: translate(50%,-50%) scale(0);
    transition: transform .2s;
}
.seek-bar:hover .handle {
    transform: translate(50%,-50%) scale(1);
}
.handle:active {
    transform: translate(50%,-50%) scale(1.4) !important;
}
var audio = document.querySelector('audio');
var playBtn = document.querySelector('button.play');
var seekBar = document.querySelector('.seek-bar');
var fillBar = seekBar.querySelector('.fill');

var pointerdown = false;

playBtn.addEventListener('click', function(){
    if (audio.paused) {
        audio.play();
    } else {
        audio.pause();
    }
});

audio.addEventListener('timeupdate', function(){
    if(pointerdown) return;

    var p = audio.currentTime / audio.duration;

    fillBar.style.width = p * 100 + '%';
});

function clamp (min, val, max) {
    return Math.min(Math.max(min, val), max);
}

function getP (e) {
    var p = (e.clientX - seekBar.offsetLeft) / seekBar.clientWidth;
    p = clamp(0, p, 1);

    return p;
}

seekBar.addEventListener('pointerdown', function(e){
    pointerdown = true;

    var p = getP(e);

    fillBar.style.width = p * 100 + '%';
});

window.addEventListener('pointerup', function(e){
    if(!pointerdown) return;

    pointerdown = false;

    var p = getP(e);

    fillBar.style.width = p * 100 + '%';

    audio.currentTime = p * audio.duration;
});

Upvotes: 1

Views: 110

Answers (1)

Jason Y
Jason Y

Reputation: 1001

This is hard to test without absolute URLs to your audio files. You are only getting the first reference to the audio selector. Using querySelectorAll will give you a NodeList. Also, you need to attach an event listener to each media object. You'll want to iterate through the NodeList to do this.

Edit: I added logic to play at the point the seek bar is positioned (respecting previous play/pause state) and also resetting the audio at the end of playback.

var audio = document.querySelectorAll('audio');
var playBtn = document.querySelectorAll('.play');
var seekBar = document.querySelectorAll('.seek-bar');
var fillBar = document.querySelectorAll('.fill');
var pointerdown = false;
var playing = undefined;

function getP(e, i) {
  var p = (e.clientX - seekBar[i].offsetLeft) / seekBar[i].clientWidth;
  p = clamp(0, p, 1);
  return p;
}

function clamp(min, val, max) {
  return Math.min(Math.max(min, val), max);
}

function updateFillBar(i, val) {
  fillBar[i].style.width = val + '%';
}

function handleTimeline(i) {
  if (pointerdown) return;
  var p = audio[i].currentTime / audio[i].duration;
  updateFillBar(i, p * 100);
}

function resetAudio(i) {
  audio[i].currentTime = 0;
  updateFillBar(i, 0);
}

function handleSeekbar(e, i) {
  pointerdown = true;
  var vidDur = audio[i].duration;
  var seekCoords = Math.round(
    (e.clientX - seekBar[i].offsetLeft) *
      (vidDur / seekBar[i].clientWidth)
  );
  handleAudioPlayback(i, seekCoords);
  var p = getP(e, i);
  updateFillBar(i, p * 100);
}

function handleButtonClick(i, time) {
  if (playing === undefined) {
    playing = i;
  }
  handleAudioPlayback(i, time);
}

function handleAudioPlayback(i, time) {
  if (playing !== i) {
    audio[playing].pause();
    playing = i;
  }
  var a = audio[i];
  if (pointerdown) {
    a.currentTime = time;
    a.play();
    pointerdown = false;
  } else if (a.paused) {
    a.play();
  } else {
    a.pause();
  }
}

audio.forEach((node, i) => {
  node.addEventListener('timeupdate', function(e) {
    handleTimeline(i);
  });
  node.addEventListener('ended', function(e) {
    resetAudio(i);
  });
  seekBar[i].addEventListener(
    'pointerdown',
    function(e) {
      handleSeekbar(e, i);
    },
    false
  );
  playBtn[i].addEventListener('click', function(e) {
    handleButtonClick(i, 0);
  });
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
body {
  background: #0f0f0f;
  color: #fff;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  touch-action: none;
}
.audio-player {
  width: 80%;
  height: 200px;
  box-shadow: 0 0 10px rgba(255, 255, 255, 0.2);
  border-radius: 10px;
}
.play {
  width: 40px;
  height: 40px;
  background-color: #fff;
  border-radius: 50%;
  margin-bottom: 30px;
  outline: none;
  border: none;
}
.play:focus {
  background-color: #f90;
}
.seek-bar {
  width: 90%;
  margin: 0 auto;
  height: 4px;
  border-radius: 4px;
  background-color: rgba(255, 255, 255, 0.2);
  display: flex;
  align-items: center;
  cursor: pointer;
}
.fill {
  height: 4px;
  border-radius: 4px;
  background-color: #fff;
  position: relative;
}
.handle {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  position: absolute;
  right: 0;
  top: 50%;
  background: #fff;
  transform: translate(50%, -50%) scale(0);
  transition: transform 0.2s;
}
.seek-bar:hover .handle {
  transform: translate(50%, -50%) scale(1);
}
.handle:active {
  transform: translate(50%, -50%) scale(1.4) !important;
}
<div class="audio-player">
  <audio src="https://milessite.com/music/music.mp3"></audio>
  <button class="play">play</button>
  <div class="seek-bar">
    <div class="fill"><div class="handle"></div></div>
  </div>
</div>
<div class="audio-player">
  <audio src="https://milessite.com/music/music1.mp3"></audio>
  <button class="play">play</button>
  <div class="seek-bar">
    <div class="fill"><div class="handle"></div></div>
  </div>
</div>

Upvotes: 1

Related Questions