HomeJavascriptCustom Music Player Javascript

Custom Music Player Javascript

Hey everyone. Welcome to today’s tutorial. In today’s tutorial, we will create a custom music player. To build this project we need HTML, CSS and Javascript.

This project is well suited for javascript intermediates. Even javascript beginners can try this project since I have explained each step with the help of comments.

The music player project might seem to be lengthy and complicated at first but I have divided the javascript code into 15 easy steps. You can easily create and customize the music player with these 15 steps.

Video Tutorial:

If you are interested to learn by coding along with a video tutorial rather than reading this blog post, you should check out the video down below. Also, I post new tricks, tips and tutorials on my youtube channel regularly. So do subscribe to my channel to stay updated with the latest tutorials.

Project Folder Structure:

Before we start coding let us take a look at the project folder structure. We create a project folder with the name – Custom Music Player. Inside this folder, we have three files – index.html, style.css and script.js. These are the HTML document, the stylesheet and the script file respectively.

HTML:

We start with the HTML code. First, copy the code below and paste it into your HTML document. This creates the elements necessary to build the structure of the music player.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Custom Music Player</title>
    <!-- Font Awesome Icons -->
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css"
      integrity="sha512-KfkfwYDsLkIlwQp6LFnl8zNdLGxu9YAA1QvwINks4PhcElQSvqcyVLLD9aMhXd13uQjoXtEKNosOWaZqXgel0g=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />
    <!-- Google Fonts -->
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&family=Roboto+Mono&display=swap"
      rel="stylesheet"
    />
    <!-- Stylesheet -->
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="music-player">
      <button id="playlist">
        <i class="fa-solid fa-angle-down"></i>
      </button>
      <img id="song-image" src="make-me-move.jpg" />
      <div class="song-details">
        <p id="song-name">Make Me Move</p>
        <p id="song-artist">Culture Code</p>
      </div>
      <div class="player-options">
        <button id="shuffle">
          <i class="fa-solid fa-shuffle"></i>
        </button>
        <button id="prev">
          <i class="fa-solid fa-backward-step"></i>
        </button>
        <button id="play">
          <i class="fa-solid fa-play"></i>
        </button>
        <button id="pause" class="hide">
          <i class="fa-solid fa-pause"></i>
        </button>
        <button id="next">
          <i class="fa-solid fa-forward-step"></i>
        </button>
        <button id="repeat">
          <i class="fa-solid fa-repeat"></i>
        </button>
      </div>
      <audio id="audio" preload="metadata"></audio>
      <div id="progress-bar">
        <div id="current-progress"></div>
      </div>
      <div class="time-container">
        <span id="current-time">0:00</span>
        <span id="max-duration">0:00</span>
      </div>
      <div id="playlist-container" class="hide">
        <button id="close-button">
          <i class="fa-solid fa-xmark"></i>
        </button>
        <ul id="playlist-songs"></ul>
      </div>
    </div>
    <!-- Script -->
    <script src="script.js"></script>
  </body>
</html>

CSS:

Next, we need to style these elements to make the music player look attractive. For this we use CSS. Now copy the code below and paste it into your stylesheet.

* {
  padding: 0;
  margin: 0;
  box-sizing: border-box;
}
body {
  height: 100vh;
  background: linear-gradient(to bottom, #2887e3 50%, #16191e 50%);
}
.music-player {
  font-size: 16px;
  width: 80vw;
  max-width: 25em;
  background-color: #ffffff;
  padding: 3em 1.8em;
  position: absolute;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 0.5em;
  box-shadow: 0.6em 1.2em 3em rgba(0, 0, 0, 0.25);
}
img {
  width: 100%;
  margin-top: 1.25em;
}
#playlist {
  float: right;
}
.song-details {
  font-family: "Poppins", sans-serif;
  text-align: center;
}
.song-details #song-name {
  font-size: 1.3em;
  font-weight: 600;
  letter-spacing: 0.3px;
}
.song-details #song-artist {
  font-size: 0.8em;
}
.player-options {
  display: flex;
  align-items: center;
  justify-content: space-around;
  padding: 0 1.25em;
  margin: 1.25em 0 0.6em 0;
}
.music-player button {
  border: none;
  background-color: transparent;
}
#play,
#pause {
  height: 2.5em;
  width: 2.5em;
  font-size: 1.8em;
  background-color: #2887e3;
  color: #ffffff;
  border-radius: 50%;
}
#prev,
#next {
  color: #16191e;
  font-size: 1.4em;
}
#shuffle,
#repeat {
  color: #949494;
  font-size: 1em;
}
.hide {
  display: none;
}
#progress-bar {
  position: relative;
  width: 100%;
  height: 0.3em;
  background-color: #eeeeee;
  margin: 1em 0;
  border-radius: 0.18em;
  cursor: pointer;
}
#current-progress {
  position: absolute;
  left: 0;
  top: 0;
  display: inline-block;
  height: 100%;
  width: 20%;
  background-color: #2887e3;
  border-radius: 0.18em;
}
.time-container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-family: "Roboto Mono", monospace;
}
#playlist-container {
  background-color: #ffffff;
  position: absolute;
  width: 100%;
  height: 100%;
  transform: translate(-50%, -50%);
  top: 50%;
  left: 50%;
  border-radius: 0.6em;
  padding: 2em 1em;
  font-family: "Poppins", sans-serif;
}
#close-button {
  background-color: transparent;
  border: none;
  height: 2em;
  width: 2em;
  cursor: pointer;
  margin-left: 90%;
}
ul {
  list-style-type: none;
}
li {
  display: flex;
  align-items: center;
  margin: 1em 0;
  cursor: pointer;
}
.playlist-song-details {
  margin-left: 1em;
}
.playlist-song-details > span {
  display: block;
}
#playlist-song-artist-album {
  color: #949494;
  font-size: 0.8em;
}
button.active i {
  color: #2887e3;
}
@media screen and (max-width: 450px) {
  .music-player {
    font-size: 14px;
  }
}

.playlist-image-container {
  width: 3em;
}

Javascript:

Lastly, we implement the functionality using javascript. Once again, copy the code below and paste it into your script file. We create the music player in 15 easy steps. These steps are:

  1. Create Initial References
  2. Create An Array For Song List
  3. Detect If It Is A Touch Device
  4. Format Time
  5. A Function To Set Song
  6. Function To Play Song
  7. Implement Function To Toggle Repeat Mode
  8. Function To Play Next Song
  9. Function To Pause Song
  10. Create Function To Play Previous Song
  11. Function To Toggle Shuffle Mode
  12. Adding Event Listener to Progress Bar
  13. Updating Progress Bar and Time
  14. Function To Create Playlist
  15. Function To Show & Hide Playlist
const prevButton = document.getElementById("prev");
const nextButton = document.getElementById("next");
const repeatButton = document.getElementById("repeat");
const shuffleButton = document.getElementById("shuffle");
const audio = document.getElementById("audio");
const songImage = document.getElementById("song-image");
const songName = document.getElementById("song-name");
const songArtist = document.getElementById("song-artist");
const pauseButton = document.getElementById("pause");
const playButton = document.getElementById("play");
const playlistButton = document.getElementById("playlist");
const maxDuration = document.getElementById("max-duration");
const currentTimeRef = document.getElementById("current-time");
const progressBar = document.getElementById("progress-bar");
const playlistContainer = document.getElementById("playlist-container");
const closeButton = document.getElementById("close-button");
const playlistSongs = document.getElementById("playlist-songs");
const currentProgress = document.getElementById("current-progress");

//index for songs
let index;

//initially loop=true
let loop = true;

const songsList = [
  {
    name: "Make Me Move",
    link: "make-me-move.mp3",
    artist: "Culture Code",
    image: "make-me-move.jpg",
  },
  {
    name: "Where We Started",
    link: "where-we-started.mp3",
    artist: "Lost Sky",
    image: "where-we-started.jpg",
  },
  {
    name: "On & On",
    link: "on-on.mp3",
    artist: "Cartoon",
    image: "on-on.jpg",
  },
  {
    name: "Throne",
    link: "throne.mp3",
    artist: "Rival",
    image: "throne.jpg",
  },
  {
    name: "Need You Now",
    link: "need-you-now.mp3",
    artist: "Venemy",
    image: "need-you-now.jpg",
  },
];

//events object
let events = {
  mouse: {
    click: "click",
  },
  touch: {
    click: "touchstart",
  },
};

let deviceType = "";

//Detect touch device

const isTouchDevice = () => {
  try {
    //We try to create TouchEvent(it would fail for desktops and throw error)
    document.createEvent("TouchEvent");
    deviceType = "touch";
    return true;
  } catch (e) {
    deviceType = "mouse";
    return false;
  }
};

//Format time (convert ms to seconds, minutes and add 0 id less than 10)
const timeFormatter = (timeInput) => {
  let minute = Math.floor(timeInput / 60);
  minute = minute < 10 ? "0" + minute : minute;
  let second = Math.floor(timeInput % 60);
  second = second < 10 ? "0" + second : second;
  return `${minute}:${second}`;
};

//set song
const setSong = (arrayIndex) => {
  //this extracts all the variables from the object
  let { name, link, artist, image } = songsList[arrayIndex];
  audio.src = link;
  songName.innerHTML = name;
  songArtist.innerHTML = artist;
  songImage.src = image;
  //display duration when metadata loads
  audio.onloadedmetadata = () => {
    maxDuration.innerText = timeFormatter(audio.duration);
  };
};

//play song
const playAudio = () => {
  audio.play();
  pauseButton.classList.remove("hide");
  playButton.classList.add("hide");
};

//repeat button
repeatButton.addEventListener("click", () => {
  if (repeatButton.classList.contains("active")) {
    repeatButton.classList.remove("active");
    audio.loop = false;
    console.log("repeat off");
  } else {
    repeatButton.classList.add("active");
    audio.loop = true;
    console.log("repeat on");
  }
});

//Next song
const nextSong = () => {
  //if loop is true then continue in normal order
  if (loop) {
    if (index == songsList.length - 1) {
      //If last song is being played
      index = 0;
    } else {
      index += 1;
    }
    setSong(index);

    playAudio();
  } else {
    //else find a random index and play that song
    let randIndex = Math.floor(Math.random() * songsList.length);
    console.log(randIndex);
    setSong(randIndex);
    playAudio();
  }
};

//pause song
const pauseAudio = () => {
  audio.pause();
  pauseButton.classList.add("hide");
  playButton.classList.remove("hide");
};

//previous song ( you can't go back to a randomly played song)
const previousSong = () => {
  if (index > 0) {
    pauseAudio();
    index -= 1;
  } else {
    //if first song is being played
    index = songsList.length - 1;
  }
  setSong(index);
  playAudio();
};

//next song when current song ends
audio.onended = () => {
  nextSong();
};

//Shuffle songs
shuffleButton.addEventListener("click", () => {
  if (shuffleButton.classList.contains("active")) {
    shuffleButton.classList.remove("active");
    loop = true;
    console.log("shuffle off");
  } else {
    shuffleButton.classList.add("active");
    loop = false;
    console.log("shuffle on");
  }
});

//play button
playButton.addEventListener("click", playAudio);

//next button
nextButton.addEventListener("click", nextSong);

//pause button
pauseButton.addEventListener("click", pauseAudio);

//prev button
prevButton.addEventListener("click", previousSong);

//if user clicks on progress bar
isTouchDevice();
progressBar.addEventListener(events[deviceType].click, (event) => {
  //start of progressBar
  let coordStart = progressBar.getBoundingClientRect().left;
  //mouse click position
  let coordEnd = !isTouchDevice() ? event.clientX : event.touches[0].clientX;
  let progress = (coordEnd - coordStart) / progressBar.offsetWidth;

  //set width to progress
  currentProgress.style.width = progress * 100 + "%";

  //set time
  audio.currentTime = progress * audio.duration;

  //play
  audio.play();
  pauseButton.classList.remove("hide");
  playButton.classList.add("hide");
});

//update progress every second
setInterval(() => {
  currentTimeRef.innerHTML = timeFormatter(audio.currentTime);
  currentProgress.style.width =
    (audio.currentTime / audio.duration.toFixed(3)) * 100 + "%";
});

//update time
audio.addEventListener("timeupdate", () => {
  currentTimeRef.innerText = timeFormatter(audio.currentTime);
});

//Creates playlist
const initializePlaylist = () => {
  for (let i in songsList) {
    playlistSongs.innerHTML += `<li class='playlistSong' onclick='setSong(${i})'>
            <div class="playlist-image-container">
                <img src="${songsList[i].image}"/>
            </div>
            <div class="playlist-song-details">
                <span id="playlist-song-name">
                    ${songsList[i].name}
                </span>
                <span id="playlist-song-artist-album">
                    ${songsList[i].artist}
                </span>
            </div>
        </li>`;
  }
};

//display playlist
playlistButton.addEventListener("click", () => {
  playlistContainer.classList.remove("hide");
});

//hide playlist
closeButton.addEventListener("click", () => {
  playlistContainer.classList.add("hide");
});

window.onload = () => {
  //initially first song
  index = 0;
  setSong(index);
  //create playlist
  initializePlaylist();
};

 

That’s it for this tutorial. Our music player is now ready. If you have any issues while creating this code you can download the source code by clicking on the download code button below. Also, if you have any queries, suggestions or feedback you can drop them in the comments below. Happy Coding!

RELATED ARTICLES

2 COMMENTS

LEAVE A REPLY

Please enter your comment!
Please enter your name here

five × one =

Most Popular