Search code examples
javascriptaudio-player

How do I add multiple instances of Javascript Audio Player in static HTML site?


I am working on a static portfolio site and have styled some Javascript audio players. The site is live here with the first audio player working almost exactly as desired (except the progress bar displays at the top of the div, I'd like it at the bottom). A photo is attached of the desired visual outcome.

enter image description here

I need five total audio players. How can I achieve this?

Current Javascript:

const audioPlayer = document.querySelector(".audio-player");
const audio = new Audio(
    "https://jsomerset.uk/images/victory.mp3"
);

console.dir(audio);

audio.addEventListener(
    "loadeddata",
    () => {
        audioPlayer.querySelector(".time .length").textContent = getTimeCodeFromNum(
            audio.duration
        );
        audio.volume = .75;
    },
    false
);

const timeline = audioPlayer.querySelector(".timeline");
timeline.addEventListener("click", e => {
    const timelineWidth = window.getComputedStyle(timeline).width;
    const timeToSeek = e.offsetX / parseInt(timelineWidth) * audio.duration;
    audio.currentTime = timeToSeek;
}, false);

setInterval(() => {
    const progressBar = audioPlayer.querySelector(".progress");
    progressBar.style.width = audio.currentTime / audio.duration * 100 + "%";
    audioPlayer.querySelector(".time .current").textContent = getTimeCodeFromNum(
        audio.currentTime
    );
}, 500);

const playBtn = audioPlayer.querySelector(".controls .toggle-play");
playBtn.addEventListener(
    "click",
    () => {
        if (audio.paused) {
            playBtn.classList.remove("play");
            playBtn.classList.add("pause");
            audio.play();
        } else {
            playBtn.classList.remove("pause");
            playBtn.classList.add("play");
            audio.pause();
        }
    },
    false
);

Solution

  • You code can't run properly, since you're selecting non existent elements.
    Check you dev tools console for errors.

    E.g. you're trying to display the current time in an element with the class time – but yout html does not contain such an element.

    Besides, you haven't defined the method getTimeCodeFromNum().

    See the cleaned up code – not usable blocks are commented out :

    const audioPlayer = document
      .querySelectorAll(".audio-player")
      .forEach((audioPlayer) => {
        const audio = new Audio(audioPlayer.dataset.src);
        //console.dir(audio);
    
    
        /*
        audio.addEventListener(
          "loadeddata",
          () => {
            audioPlayer.querySelector(
              ".time .length"
            ).textContent = getTimeCodeFromNum(audio.duration);
            audio.volume = 0.75;
          },
          false
        );
        */
    
    
        const timeline = audioPlayer.querySelector(".timeline");
        timeline.addEventListener(
          "click",
          (e) => {
            const timelineWidth = window.getComputedStyle(timeline).width;
            const timeToSeek =
              (e.offsetX / parseInt(timelineWidth)) * audio.duration;
            audio.currentTime = timeToSeek;
          },
          false
        );
    
    
        setInterval(() => {
          const progressBar = audioPlayer.querySelector(".progress");
          progressBar.style.width =
            (audio.currentTime / audio.duration) * 100 + "%";
          /*
          audioPlayer.querySelector(
            ".time .current"
          ).textContent = getTimeCodeFromNum(audio.currentTime);
          */
        }, 500);
    
    
        const playBtn = audioPlayer.querySelector(".controls .toggle-play");
        playBtn.addEventListener(
          "click",
          () => {
            if (audio.paused) {
              playBtn.classList.remove("play");
              playBtn.classList.add("pause");
              audio.play();
            } else {
              playBtn.classList.remove("pause");
              playBtn.classList.add("play");
              audio.pause();
            }
          },
          false
        );
    
        /*
        audioPlayer
          .querySelector(".volume-button")
          .addEventListener("click", () => {
            const volumeEl = audioPlayer.querySelector(".volume-container .volume");
            audio.muted = !audio.muted;
            if (audio.muted) {
              volumeEl.classList.remove("icono-volumeMedium");
              volumeEl.classList.add("icono-volumeMute");
            } else {
              volumeEl.classList.add("icono-volumeMedium");
              volumeEl.classList.remove("icono-volumeMute");
            }
          });
          */
      });
    body {
      background: #000
    }
    
    .audio-player {
      display: grid;
      grid-template-rows: 6px auto;
      overflow: hidden;
      height: 200px;
      width: 100vw;
      color: #efefef;
    }
    
    .timeline {
      background: none;
      width: 100%;
      position: relative;
      cursor: pointer;
      height: 5px;
    }
    
    .progress {
      background: #efefef;
      width: 0%;
      height: 5px;
      transition: 0.25s;
      -webkit-transition: 0.25s;
    }
    
    .controls {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100px;
    }
    
    .controls * {
      display: flex;
      justify-content: center;
      align-items: center;
    }
    
    .play {
      cursor: pointer;
      position: relative;
      left: 0;
      height: 0;
      width: 0;
      border: 7px solid #0000;
      border-left: 13px solid white;
    }
    
    .pause {
      height: 15px;
      width: 20px;
      cursor: pointer;
      position: absolute;
      margin-left: 15px;
    }
    
    .pause:before {
      position: absolute;
      top: 0;
      left: 0px;
      background: white;
      content: "";
      height: 15px;
      width: 3px;
    }
    
    .pause:after {
      position: absolute;
      top: 0;
      right: 9px;
      background: white;
      content: "";
      height: 15px;
      width: 3px;
    }
    <div class="audio-player a-one font" data-src="https://jsomerset.uk/images/swain.mp3">
      <div class="timeline">
        <div class="progress" style="width: 0%;"></div>
      </div>
      <div class="name">Action</div>
      <div class="controls">
        <div class="play-container">
          <div class="toggle-play play">
          </div>
        </div>
      </div>
    </div>
    
    <div class="audio-player a-two font" data-src="https://jsomerset.uk/images/victory.mp3">
      <div class="timeline">
        <div class="progress"></div>
      </div>
      <div class="name">Victory Song</div>
      <div class="controls">
        <div class="play-container">
          <div class="toggle-play play">
          </div>
        </div>
      </div>
    </div>