使用JavaScript创建音乐播放器的案例详解

英文 | https://www.geeksforgeeks.org/create-a-music-player-using-javascript/?ref=leftbar-rightbar

翻译 | web前端开发(ID:web_qdkf)

随着越来越多的用户使用流媒体,在线媒体播放器已成为消费在Internet上必不可少的媒介。音乐播放器允许人们在任何浏览器中欣赏音乐,并支持离线音乐播放器的许多功能。

我们将创建一个用户界面干净的音乐播放器,可用于在浏览器中播放音乐。我们还将实现搜索和音量控制等功能。HTML在HTMLMediaElement接口中有几种方法,可用于播放音频文件并控制其播放,而无需使用任何其他库。

我们首先将创建HTML,使用HTML布局定义播放器的结构,再通过使用CSS样式使其外观看起来更美观,然后使用JavaScript编写它的所有功能,以及编写播放器逻辑。

HTML布局
HTML布局定义了将在页面上显示的元素结构。播放器可以分为以下几部分:

  • 详细信息部分:此部分显示正在播放的当前曲目的详细信息。它包括曲目编号,曲目专辑,曲目名称和曲目艺术家。

  • 按钮部分:此部分显示用于控制曲目播放的按钮。它包括播放/暂停按钮,上上一曲和下一曲的曲目按钮。它们将使用onclick()方法来实现,该方法调用JavaScript文件中定义的特定函数。

  • 滑块部分:此部分包含可用于控制播放和音量的搜寻滑块和音量滑块。

我们将使用FontAwesome图标来获取页面上使用的所有按钮的图标。文件中还将链接我们稍后将编写的自定义的CSS和JavaScript。

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 p 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 p 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 p 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 p 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>

CSS样式
使用CSS我们可以设置不同部分的样式,以使其在视觉上更具吸引力:

  • flex布局用于排列播放器的各种元素,并将它们与页面的中间对齐。

  • 轨道艺术图像具有固定的尺寸,并使用border-radius属性进行了舍入。

  • 这两个滑块已经通过使用外观属性从其默认外观进行了修改。更改高度和背景以适合配色方案。它们还具有轻微的透明度,可以使用transition属性平滑过渡到完全不透明。

  • 所有播放控件的cursor属性均已设置,以便每当鼠标悬停在其上时,它将变为指针。

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; }

HTML布局和CSS样式的结果将显示以下外观:

播放器的JavaScript逻辑:

播放器的逻辑在JavaScript文件中定义。有几种功能可以共同处理播放器的所有功能。

步骤1:定义所有变量并访问HTML元素
首先使用querySelector()方法选择HTML布局中要动态更改的必需元素。然后为它们分配变量名,以便可以对其进行访问和修改。还定义了将在整个程序中访问的其他变量。



// 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", 
  }, 
]; 

步骤2:从轨道列表中加载新轨道在轨道列表中,
所有必须播放的轨道都被定义为对象。这些对象包含名称,艺术家,图像和轨道路径等属性。然后可以使用其轨道索引访问每个轨道。

要加载曲目,loadTrack()定义了一个函数,该函数处理以下事情:

  • 重置前一曲
    目的所有值将创建一个resetValues()函数,该函数在将新曲目开始之前,将持续时间值和滑块重置为初始值。这样可以防止在加载新轨道时搜索滑块跳动。

  • 加载轨道
    使用其src属性为音频元素分配一个新的源。可以给它来自文件系统或URL的任何路径。然后在音频元素上使用load()方法来准备轨道。

  • 更新要显示
    的轨迹图从阵列中获取轨迹图,并在backgroundImage属性的帮助下进行分配。

  • 更新要显示
    的轨道详细信息从数组中获取轨道详细信息,并在textContent属性的帮助下进行分配。

  • 将事件侦听器添加到轨道
    media元素上添加了两个事件侦听器,第一个用于更新当前搜索位置,第二个侦听器用于在当前轨道结束时加载下一个轨道。

  • 设置随机的彩色背景
    通过对使用的红色,绿色和蓝色值进行随机化并将其设置为颜色来生成彩色背景。通过使用上的transition属性来为效果设置动画background-color。

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; } 
// Functiom to reset all values to their default function resetValues() {   curr_time.textContent = "00:00";   total_duration.textContent = "00:00";   seek_slider.value = 0; }

步骤3:配置播放器按钮
函数playTrack()句柄当前加载的曲目的播放。所述play()的HTMLMediaElement API的方法用于此功能。按钮的图标也变为暂停图标。这是通过使用FontAwesome库中的图标之一并使用innerHTML插入它来完成的。

一个函数pauseTrack()处理当前加载的曲目的播放。所述pause()的HTMLMediaElement API的方法用于此功能。按钮的图标也变回播放图标。这是通过使用FontAwesome库中的图标之一并使用innerHTML插入它来完成的。

根据轨道当前是否正在播放来调用这两个功能。playpause()函数处理轨道的实际播放/暂停控制。

函数prevTrack()处理上一曲目的加载并向后移动索引。当索引到达第一个曲目时,索引会重置为最后一个曲目。上面定义的loadTrack()方法用于加载新轨道。

类似地,一个函数nextTrack()处理下一个曲目的加载并向前移动索引。当索引到达最后一个音轨时,索引会重置为第一个音轨。上面定义的loadTrack()方法用于加载新轨道。

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; 
  // Load and play the new track   loadTrack(track_index);   playTrack(); }

步骤4:配置滑块部分

我们将设置两个滑块,分别控制搜索滑块和音量滑块。

  • 搜索滑块
    “搜索”滑块通过用轨道的当前时间进行更新来在滑块上显示当前播放位置。创建一个新函数seekUpdate(),以处理相对于轨道当前时间的搜索滑块的更新。搜索滑块的位置是使用value属性计算和设置的。

  • 现在,每次轨道进一步前进时都必须调用此函数。这可以通过安排每秒更新一次来完成。可以使用setInterval()方法(间隔为1000毫秒)来完成此操作。每次加载新曲目时,都会清除此计时器。

  • 此功能还可以处理经过的时间和曲目的总持续时间的更改,该更改在每次触发时都会更新。分钟和秒分别计算并正确格式化以显示。

  • 音量滑块
    音量滑块用于显示曲目的当前音量。创建了一个新函数setVolume(),每当用户对其进行更改时,该函数都会处理音量滑块的设置。

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;   } }

步骤5:启动播放器

通过调用loadTrack()函数加载第一首曲目。这将从轨道列表中加载第一个轨道,并更新轨道的所有详细信息。然后,用户可以使用“播放”按钮开始播放曲目。上一个和下一个曲目按钮将分别加载上一个和下一个曲目并开始播放。

曲目播放完毕后,将自动加载下一个曲目。用户可以使用搜索滑块在轨道中搜索位置。也可以使用音量滑块调节音量。

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

最后演示

现在可以在任何浏览器中使用播放器了。可以将新曲目添加到曲目列表,以播放你选择的音乐。

本文完~

视频播放

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值