Crear un reproductor de música usando JavaScript

A medida que los usuarios adoptan cada vez más la transmisión, los reproductores multimedia en línea se han vuelto esenciales para consumir medios en Internet. Los reproductores de música permiten disfrutar de la música en cualquier navegador y admiten muchas de las características de un reproductor de música sin conexión.
Crearemos un reproductor de música con una interfaz de usuario limpia que se puede usar para reproducir música en el navegador. También implementaremos características como búsqueda y control de volumen. HTML tiene varios métodos en la interfaz HTMLMediaElement que se pueden usar para reproducir archivos de audio y controlar su reproducción sin usar ninguna otra biblioteca.
Comenzaremos creando el diseño HTML primero que define la estructura del reproductor, haremos que se vea bien estilizando usando CSS y luego escribiremos la lógica del reproductor para todas las funciones en JavaScript.
 

El diseño HTML 
El diseño HTML define la estructura del elemento que se mostrará en la página. El jugador se puede dividir en las siguientes porciones:
 

  • Porción de detalles: esta sección muestra los detalles de la pista actual que se está reproduciendo. Incluye el número de la pista, el álbum de la pista, el nombre de la pista y el artista de la pista.
  • Porción de botones: esta sección muestra los botones que se utilizan para controlar la reproducción de la pista. Incluye el botón de reproducción/pausa, los botones de pista anterior y siguiente. Tendrían un método onclick() que llama a una función específica definida en el archivo JavaScript.
  • Porción de controles deslizantes: esta sección contiene el control deslizante de búsqueda y el control deslizante de volumen que se pueden usar para controlar la reproducción y el volumen.

Usaremos los íconos de FontAwesome para obtener los íconos de todos los botones que se usan en la página. El CSS personalizado y el JavaScript que escribiremos más adelante también están vinculados en el archivo.
El código HTML es el siguiente: 
 

html

<!DOCTYPE html>
<html lang="en">
<head>
  <title>Simple Music Player</title>
  <!-- Load FontAwesome icons -->
  <link rel="stylesheet"
        href=
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css">
 
  <!-- Load the custom CSS style file -->
  <link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
  <div class="player">
 
    <!-- Define the section for displaying details -->
    <div class="details">
      <div class="now-playing">PLAYING x OF y</div>
      <div class="track-art"></div>
      <div class="track-name">Track Name</div>
      <div class="track-artist">Track Artist</div>
    </div>
 
    <!-- Define the section for displaying track buttons -->
    <div class="buttons">
      <div class="prev-track" onclick="prevTrack()">
        <i class="fa fa-step-backward fa-2x"></i>
      </div>
      <div class="playpause-track" onclick="playpauseTrack()">
        <i class="fa fa-play-circle fa-5x"></i>
      </div>
      <div class="next-track" onclick="nextTrack()">
        <i class="fa fa-step-forward fa-2x"></i>
      </div>
    </div>
 
    <!-- Define the section for displaying the seek slider-->
    <div class="slider_container">
      <div class="current-time">00:00</div>
      <input type="range" min="1" max="100"
        value="0" class="seek_slider" onchange="seekTo()">
      <div class="total-duration">00:00</div>
    </div>
 
    <!-- Define the section for displaying the volume slider-->
    <div class="slider_container">
      <i class="fa fa-volume-down"></i>
      <input type="range" min="1" max="100"
        value="99" class="volume_slider" onchange="setVolume()">
      <i class="fa fa-volume-up"></i>
    </div>
  </div>
 
  <!-- Load the main script for the player -->
  <script src="main.js"></script>
</body>
</html>

El Estilo CSS 
Usando CSS podemos diseñar las diferentes partes para hacerlo más atractivo visualmente: 
 

  • El diseño flexible se utiliza para organizar los diversos elementos del reproductor y alinearlos en el medio de la página.
  • A la imagen de arte de la pista se le da una dimensión fija y se redondea usando la propiedad border-radius.
  • Se ha modificado el aspecto predeterminado de los dos controles deslizantes mediante la propiedad de apariencia. La altura y el fondo se cambian para adaptarse a la combinación de colores. También reciben una ligera transparencia que cambia suavemente a la opacidad total utilizando la propiedad de transición.
  • Todos los controles de reproducción tienen su propiedad de cursor configurada para que cambie a un puntero cada vez que el mouse pasa sobre él.

css

body {
  background-color: lightgreen;
 
  /* Smoothly transition the background color */
  transition: background-color .5s;
}
 
/* Using flex with the column direction to
   align items in a vertical direction */
.player {
  height: 95vh;
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
}
 
.details {
  display: flex;
  align-items: center;
  flex-direction: column;
  justify-content: center;
  margin-top: 25px;
}
 
.track-art {
  margin: 25px;
  height: 250px;
  width: 250px;
  background-image: URL(
     "https://source.unsplash.com/Qrspubmx6kE/640x360");
  background-size: cover;
  background-position: center;
  border-radius: 15%;
}
 
/* Changing the font sizes to suitable ones */
.now-playing {
  font-size: 1rem;
}
 
.track-name {
  font-size: 3rem;
}
 
.track-artist {
  font-size: 1.5rem;
}
 
/* Using flex with the row direction to
   align items in a horizontal direction */
.buttons {
  display: flex;
  flex-direction: row;
  align-items: center;
}
 
.playpause-track,
.prev-track,
.next-track {
  padding: 25px;
  opacity: 0.8;
 
  /* Smoothly transition the opacity */
  transition: opacity .2s;
}
 
/* Change the opacity when mouse is hovered */
.playpause-track:hover,
.prev-track:hover,
.next-track:hover {
  opacity: 1.0;
}
 
/* Define the slider width so that it scales properly */
.slider_container {
  width: 75%;
  max-width: 400px;
  display: flex;
  justify-content: center;
  align-items: center;
}
 
/* Modify the appearance of the slider */
.seek_slider, .volume_slider {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  height: 5px;
  background: black;
  opacity: 0.7;
  -webkit-transition: .2s;
  transition: opacity .2s;
}
 
/* Modify the appearance of the slider thumb */
.seek_slider::-webkit-slider-thumb,
.volume_slider::-webkit-slider-thumb {
  -webkit-appearance: none;
  -moz-appearance: none;
  appearance: none;
  width: 15px;
  height: 15px;
  background: white;
  cursor: pointer;
  border-radius: 50%;
}
 
/* Change the opacity when mouse is hovered */
.seek_slider:hover,
.volume_slider:hover {
  opacity: 1.0;
}
 
.seek_slider {
  width: 60%;
}
 
.volume_slider {
  width: 30%;
}
 
.current-time,
.total-duration {
  padding: 10px;
}
 
i.fa-volume-down,
i.fa-volume-up {
  padding: 10px;
}
 
/* Change the mouse cursor to a pointer
   when hovered over */
i.fa-play-circle,
i.fa-pause-circle,
i.fa-step-forward,
i.fa-step-backward {
  cursor: pointer;
}

El resultado del diseño HTML y el estilo CSS daría la siguiente apariencia:
 

html_css_output

Lógica JavaScript del reproductor:
La lógica del reproductor se define en el archivo JavaScript. Hay varias funciones que trabajan juntas para manejar todas las funciones del reproductor.
Paso 1: Definición de todas las variables y acceso a los elementos HTML 
Los elementos requeridos en el diseño HTML que se van a cambiar dinámicamente se seleccionan primero usando el método querySelector(). Luego se les asignan nombres de variables para que puedan ser accedidos y modificados. También se definen otras variables a las que se accedería a lo largo del programa.
 

javascript

// Select all the elements in the HTML page
// and assign them to a variable
let now_playing = document.querySelector(".now-playing");
let track_art = document.querySelector(".track-art");
let track_name = document.querySelector(".track-name");
let track_artist = document.querySelector(".track-artist");
 
let playpause_btn = document.querySelector(".playpause-track");
let next_btn = document.querySelector(".next-track");
let prev_btn = document.querySelector(".prev-track");
 
let seek_slider = document.querySelector(".seek_slider");
let volume_slider = document.querySelector(".volume_slider");
let curr_time = document.querySelector(".current-time");
let total_duration = document.querySelector(".total-duration");
 
// Specify globally used values
let track_index = 0;
let isPlaying = false;
let updateTimer;
 
// Create the audio element for the player
let curr_track = document.createElement('audio');
 
// Define the list of tracks that have to be played
let track_list = [
  {
    name: "Night Owl",
    artist: "Broke For Free",
    image: "Image URL",
    path: "Night_Owl.mp3"
  },
  {
    name: "Enthusiast",
    artist: "Tours",
    image: "Image URL",
    path: "Enthusiast.mp3"
  },
  {
    name: "Shipping Lanes",
    artist: "Chad Crouch",
    image: "Image URL",
    path: "Shipping_Lanes.mp3",
  },
];

Paso 2: Cargar una nueva pista desde la lista de pistas 
Todas las pistas que deben reproducirse se definen en la lista de pistas como objetos. Estos objetos contienen propiedades como el nombre, el artista, la imagen y la ruta a la pista. A continuación, se puede acceder a cada una de las pistas utilizando su índice de pista.
Para cargar una pista, se define una función loadTrack() que maneja las siguientes cosas: 
 

  • Restablecer todos los valores de la pista anterior 
    Se crea una función resetValues() que maneja el restablecimiento del valor de duración y el control deslizante a sus valores iniciales antes de que comience una nueva pista. Esto evita que el control deslizante de búsqueda salte mientras se carga la nueva pista.
  • Cargando la pista 
    Al elemento de audio se le asigna una nueva fuente utilizando su propiedad src. Se le puede dar cualquier ruta desde el sistema de archivos o una URL. Luego se usa el método load() en el elemento de audio para preparar la pista.
  • Actualización de la imagen de la pista que se mostrará 
    La imagen de la pista se extrae de la array y se asigna con la ayuda de la propiedad backgroundImage.
  • Actualización de los detalles de la pista que se mostrarán 
    Los detalles de la pista se obtienen de la array y se asignan con la ayuda de la propiedad textContent.
  • Adición de detectores de eventos a la pista 
    El elemento multimedia tiene dos detectores de eventos agregados, el primero para actualizar la posición de búsqueda actual y el segundo para cargar la siguiente pista cuando finaliza la pista actual.
  • Configuración de un fondo de color aleatorio 
    Se genera un fondo de color aleatorizando los valores de rojo, verde y azul utilizados y estableciéndolo como un color. El efecto se anima usando la propiedad de transición en el color de fondo.

javascript

function loadTrack(track_index) {
  // Clear the previous seek timer
  clearInterval(updateTimer);
  resetValues();
 
  // Load a new track
  curr_track.src = track_list[track_index].path;
  curr_track.load();
 
  // Update details of the track
  track_art.style.backgroundImage =
     "url(" + track_list[track_index].image + ")";
  track_name.textContent = track_list[track_index].name;
  track_artist.textContent = track_list[track_index].artist;
  now_playing.textContent =
     "PLAYING " + (track_index + 1) + " OF " + track_list.length;
 
  // Set an interval of 1000 milliseconds
  // for updating the seek slider
  updateTimer = setInterval(seekUpdate, 1000);
 
  // Move to the next track if the current finishes playing
  // using the 'ended' event
  curr_track.addEventListener("ended", nextTrack);
 
  // Apply a random background color
  random_bg_color();
}
 
function random_bg_color() {
  // Get a random number between 64 to 256
  // (for getting lighter colors)
  let red = Math.floor(Math.random() * 256) + 64;
  let green = Math.floor(Math.random() * 256) + 64;
  let blue = Math.floor(Math.random() * 256) + 64;
 
  // Construct a color withe the given values
  let bgColor = "rgb(" + red + ", " + green + ", " + blue + ")";
 
  // Set the background to the new color
  document.body.style.background = bgColor;
}
 
// Function to reset all values to their default
function resetValues() {
  curr_time.textContent = "00:00";
  total_duration.textContent = "00:00";
  seek_slider.value = 0;
}

Paso 3: Configuración de los botones del reproductor 
Una función playTrack() maneja la reproducción de la pista cargada actualmente. El método play() de la API HTMLMediaElement se utiliza para esta función. El icono del botón también cambia al icono de pausa. Esto se hace usando uno de los íconos de la biblioteca FontAwesome e insertándolo usando innerHTML.
Una función pauseTrack() maneja la reproducción de la pista cargada actualmente. El método pause() de la API HTMLMediaElement se utiliza para esta función. El icono del botón también vuelve a cambiar al icono de reproducción. Esto se hace usando uno de los íconos de la biblioteca FontAwesome e insertándolo usando innerHTML.
Estas dos funciones se invocan dependiendo de si la pista se está reproduciendo actualmente o no. La función playpause() maneja el control real de reproducción/pausa de la pista. 
Una función prevTrack() maneja la carga de la pista anterior y mueve el índice hacia atrás. El índice se restablece a la última pista cuando el índice llega a la primera pista. El método loadTrack() definido anteriormente se usa para cargar la nueva pista.
De manera similar, una función nextTrack() maneja la carga de la siguiente pista y mueve el índice hacia adelante. El índice se restablece a la primera pista cuando el índice llega a la última pista. El método loadTrack() definido anteriormente se usa para cargar la nueva pista.
 

javascript

function playpauseTrack() {
  // Switch between playing and pausing
  // depending on the current state
  if (!isPlaying) playTrack();
  else pauseTrack();
}
 
function playTrack() {
  // Play the loaded track
  curr_track.play();
  isPlaying = true;
 
  // Replace icon with the pause icon
  playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
}
 
function pauseTrack() {
  // Pause the loaded track
  curr_track.pause();
  isPlaying = false;
 
  // Replace icon with the play icon
  playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';
}
 
function nextTrack() {
  // Go back to the first track if the
  // current one is the last in the track list
  if (track_index < track_list.length - 1)
    track_index += 1;
  else track_index = 0;
 
  // Load and play the new track
  loadTrack(track_index);
  playTrack();
}
 
function prevTrack() {
  // Go back to the last track if the
  // current one is the first in the track list
  if (track_index > 0)
    track_index -= 1;
  else track_index = track_list.length - 1;
   
  // Load and play the new track
  loadTrack(track_index);
  playTrack();
}

Paso 4: Configuración de la parte de los controles deslizantes
Configuraremos dos controles deslizantes que controlan el control deslizante de búsqueda y el control deslizante de volumen.
 

  • El control deslizante 
    de búsqueda El control deslizante de búsqueda muestra la posición de reproducción actual en un control deslizante actualizándolo con el tiempo actual de la pista. Se crea una nueva función seekUpdate() que maneja la actualización del control deslizante de búsqueda en relación con el tiempo actual de la pista. La posición del control deslizante de búsqueda se calcula y establece mediante la propiedad de valor. 
    Ahora, esta función debe llamarse cada vez que la pista avanza más. Esto se puede hacer programándolo para que se actualice cada segundo. Esto se puede hacer usando el método setInterval() con un intervalo de 1000 milisegundos. Este temporizador se borra cada vez que se carga una nueva pista.
    Esta función también maneja el cambio del tiempo transcurrido y la duración total de la pista, que se actualiza cada vez que se activa esta función. Los minutos y los segundos se calculan por separado y se formatean correctamente para que se muestren. 
     
  • El control deslizante 
    de volumen El control deslizante de volumen se utiliza para mostrar y establecer el volumen actual de la pista. Se crea una nueva función setVolume() que maneja la configuración del control deslizante de volumen cada vez que el usuario lo cambia. 
     

javascript

function seekTo() {
  // Calculate the seek position by the
  // percentage of the seek slider
  // and get the relative duration to the track
  seekto = curr_track.duration * (seek_slider.value / 100);
 
  // Set the current track position to the calculated seek position
  curr_track.currentTime = seekto;
}
 
function setVolume() {
  // Set the volume according to the
  // percentage of the volume slider set
  curr_track.volume = volume_slider.value / 100;
}
 
function seekUpdate() {
  let seekPosition = 0;
 
  // Check if the current track duration is a legible number
  if (!isNaN(curr_track.duration)) {
    seekPosition = curr_track.currentTime * (100 / curr_track.duration);
    seek_slider.value = seekPosition;
 
    // Calculate the time left and the total duration
    let currentMinutes = Math.floor(curr_track.currentTime / 60);
    let currentSeconds = Math.floor(curr_track.currentTime - currentMinutes * 60);
    let durationMinutes = Math.floor(curr_track.duration / 60);
    let durationSeconds = Math.floor(curr_track.duration - durationMinutes * 60);
 
    // Add a zero to the single digit time values
    if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
    if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
    if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
    if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; }
 
    // Display the updated duration
    curr_time.textContent = currentMinutes + ":" + currentSeconds;
    total_duration.textContent = durationMinutes + ":" + durationSeconds;
  }
}

Paso 5: Iniciar el reproductor
La primera pista se carga llamando a la función loadTrack(). Esto cargará la primera pista de la lista de pistas y actualizará todos los detalles de la pista. Luego, el usuario puede comenzar a reproducir la pista usando el botón de reproducción. El botón de pista anterior y siguiente cargaría la pista anterior y siguiente respectivamente y comenzaría a reproducirlas.
La siguiente pista se carga automáticamente cuando una pista termina de reproducirse. El usuario puede buscar una posición en la pista utilizando el control deslizante de búsqueda. El volumen también se puede ajustar con el control deslizante de volumen.
 

javascript

// Load the first track in the tracklist
loadTrack(track_index);

Demostración final
El reproductor ahora está listo para ser utilizado en cualquier navegador. Se pueden agregar nuevas pistas a la lista de pistas para reproducir la música de su elección.
 

Pruebe en línea: https://ide.geeksforgeeks.org/tryit.php/T3gdWUn4aX
Código fuente: https://github.com/sayantanm19/js-music-player
 

JavaScript es mejor conocido por el desarrollo de páginas web, pero también se usa en una variedad de entornos que no son de navegador. Puede aprender JavaScript desde cero siguiendo este tutorial de JavaScript y ejemplos de JavaScript.

Publicación traducida automáticamente

Artículo escrito por sayantanm19 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *