Categorieën bekijken

Audio Player

4 min leestijd

Table of Contents

Met onderstaande code kan je op een eenvoudige manier styling geven aan een audio player. Natuurlijk mist deze wat onderdelen ten opzichte van de standaard browser player, maar je hebt hiermee wel meer mogelijkheden voor de styling. Op dit moment werkt dit maar met 1 per pagina (onderstaande kan je gewoon in een Gutenburg block zetten), maar dit zal je vast op een redelijk makkelijke manier variabel kunnen maken.

HTML / PHP #

<?php
   global $site_sets;
   $audio_url = get_field('audio_url');
?>

<div class="audio-container">

   <audio controls>
      <source src="<?php echo($audio_url); ?>"  type="audio/mp3">
   </audio> 

   <div class="audio-player">
      <div class="controls">

         <div class="play-container">
            <div class="toggle-play play"></div>
         </div>

         <div class="time">
            <div class="current">0:00</div>
            <div class="divider">/</div>
            <div class="length"></div>
         </div>

         <div class="timeline">
            <div class="progress"></div>
         </div>

         <div class="volume-container">
            <div class="volume-button">
               <div class="volume icono-volumeMedium"></div>
            </div>
            <div class="volume-slider">
               <div class="volume-percentage"></div>
            </div>
         </div>

      </div>
   </div>
</div>

CSS #

.audio-container {
   position: relative;
   margin: var(--margin) 0;

   audio {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      opacity: 0;
      z-index: -1;
   }
}

.audio-player {
   width: 50%;
   height: 65px;
   background-color: var(--brand_primary);
   color: #FFFFFF;
   overflow: hidden;
   display: flex;
   align-items: center;

   @media(max-width: 991px) {
      width: 100%;
   }

   .timeline {
      background-color: #FFFFFF;
      width: 100%;
      position: relative;
      cursor: pointer;
      justify-content: flex-start !important;
      height: 5px;

      .progress {
         background: var(--brand_accent);
         width: 0%;
         height: 100%;
         border-radius: 0;
      }
   }

   .controls {
      display: flex;
      align-items: center;
      width: 100%;

      >* {
         display: flex;
         justify-content: center;
         align-items: center;
      }

      .play-container {
         flex-shrink: 0;
      }

      .toggle-play {
         width: 65px;
         height: 65px;
         display: flex;
         align-items: center;
         justify-content: center;
         cursor: pointer;
         background: var(--brand_secondary);
         transition: 0.2s ease-in-out;

         &:before {
            transition: 0.2s ease-in-out;
         }

         &:hover {
            background: var(--brand_secondary-dark);
         }

         &.play {
            &:before {
               content: '\f04b';
               font-size: 1.2rem;
               font-family: "Font Awesome 5 Free";
               font-weight: 900;
               color: #FFFFFF;
            }
         }

         &.pause {
            &:before {
               content: '\f04c';
               font-size: 1.2rem;
               font-family: "Font Awesome 5 Free";
               font-weight: 900;
               color: #FFFFFF;
            }
         }
      }

      .time {
         display: flex;
         padding: 0 20px;
         font-size: 0.9rem;

         .divider {
            margin: 0 5px;
         }
      }

      .volume-container {
         flex-shrink: 0;
         position: relative;

         .volume-button {
            width: 65px;
            height: 65px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;

            &:hover {
               .volume:before {
                  color: var(--brand_secondary-dark) !important;
               }
            }
         }

         .volume {

            &:before {
               transition: 0.2s ease-in-out;
            }

            &.icono-volumeMedium {
               &:before {
                  content: '\f028';
                  font-size: 1.2rem;
                  font-family: "Font Awesome 5 Free";
                  font-weight: 900;
                  color: #FFFFFF;
               }
            }

            &.icono-volumeMute {
               &:before {
                  content: '\f6a9';
                  font-size: 1.2rem;
                  font-family: "Font Awesome 5 Free";
                  font-weight: 900;
                  color: #FFFFFF;
               }
            }
         }

         .volume-slider {
            display: none;
            position: absolute;
            top: 0;
            left: 0;
            z-index: 1;
            width: 100px;
            height: 15px;
            background: red;
            transition: .25s;

            .volume-percentage {
               background: coral;
               height: 100%;
               width: 75%;
            }
         }
      }
   }
}

JS #

function audioPlayer() {

   if (jQuery('.audio-container')[0]){
      // Do something if class exists
      const audioFile = jQuery(".audio-container").find('audio source').attr('src');
      const audio = new Audio(
         audioFile
      );

      const audioPlayer = document.querySelector(".audio-player");

      console.dir(audio);

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

      //click on timeline to skip around
      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);

      //click volume slider to change volume
      const volumeSlider = audioPlayer.querySelector(".controls .volume-slider");
      volumeSlider.addEventListener('click', e => {
      const sliderWidth = window.getComputedStyle(volumeSlider).width;
      const newVolume = e.offsetX / parseInt(sliderWidth);
      audio.volume = newVolume;
      audioPlayer.querySelector(".controls .volume-percentage").style.width = newVolume * 100 + '%';
      }, false)

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

      //toggle between playing and pausing on button click
      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");
      }
      });

      //turn 128 seconds into 2:08
      function getTimeCodeFromNum(num) {
      let seconds = parseInt(num);
      let minutes = parseInt(seconds / 60);
      seconds -= minutes * 60;
      const hours = parseInt(minutes / 60);
      minutes -= hours * 60;

      if (hours === 0) return `${minutes}:${String(seconds % 60).padStart(2, 0)}`;
      return `${String(hours).padStart(2, 0)}:${minutes}:${String(
         seconds % 60
      ).padStart(2, 0)}`;
      }
   }
}

Mogelijk gemaakt door BetterDocs