Simple Music Player

По мере того, как пользователи все чаще используют потоковую передачу, онлайн-медиаплееры стали незаменимыми для потребления мультимедиа в Интернете. Музыкальные проигрыватели позволяют слушать музыку в любом браузере и поддерживают множество функций автономного музыкального проигрывателя.
Мы будем создавать музыкальный проигрыватель с чистым пользовательским интерфейсом, который можно использовать для воспроизведения музыки в браузере. Мы также реализуем такие функции, как ползунок времени и регулировка громкости. HTML имеет несколько методов в интерфейсе HTMLMediaElement, которые можно использовать для воспроизведения аудиофайлов и управления их воспроизведением без использования какой-либо другой библиотеки.
Мы начнем с создания макета HTML, определяющего структуру проигрывателя, придадим ему красивый вид с помощью стилей с помощью CSS, а затем напишем логику проигрывателя для всех функций на JavaScript.

Макет HTML
HTML определяет структуру элементов, которые будут отображаться на странице. Плеер можно разделить на следующие части:
 
• Часть сведений : в этом разделе отображаются сведения о текущей воспроизводимой дорожке. Он включает в себя номер дорожки, альбом дорожки, название дорожки и исполнителя дорожки.
• Часть кнопок: в этом разделе показаны кнопки, которые используются для управления воспроизведением трека. Он включает в себя кнопку воспроизведения/паузы, кнопки перехода к предыдущему и следующему треку. У них будет метод onclick(), который вызывает определенную функцию в файле JavaScript.
• Ползунки: этот раздел содержит ползунок длительности трека и ползунок громкости, которые можно использовать для управления воспроизведением и громкостью.
Мы будем использовать значки FontAwesome, чтобы получить значки для всех кнопок, используемых на странице. Пользовательские CSS и JavaScript, которые мы напишем позже, также связаны в файле.
HTML-код выглядит следующим образом: 
 
HTML
index.html

<!DOCTYPE html>
<html lang="ru">
<head>
<title>Simple Music Player</title>
<!-- Загружаем иконки FontAwesome -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css">
<!-- подключаем css файл стиля -->
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<div class="player">
<!-- Определяем раздел для отображения деталей -->
<div class="details">
<div class="now-playing">PLAYING x OF y</div>
<div class="track-art"></div>
<div class="track-name">Имя трека</div>
<div class="track-artist">Артист</div>
</div>
<!-- Определяем раздел для отображения кнопок трека -->
<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>
<!-- Определяем раздел для отображения ползунка длительности трека -->
<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>
<!-- Определяем раздел для отображения ползунка громкости -->
<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>
<!-- подключаем основной скрипт для плеера -->
<script src="main.js"></script>
</body>
</html>

Стилизация CSS 
Используя CSS, мы можем стилизовать различные части, чтобы сделать их более привлекательными: 
 
• Гибкая компоновка используется для размещения различных элементов проигрывателя и выравнивания их по середине страницы.
• Изображение трека имеет фиксированный размер и округляется с помощью свойства border-radius.
• Два ползунка были изменены по сравнению с их внешним видом по умолчанию с помощью свойства внешнего вида. Высота и фон изменены в соответствии с цветовой схемой. Им также придается небольшая прозрачность, которая плавно переходит в полную непрозрачность с помощью свойства перехода.
• Все элементы управления воспроизведением имеют свойство курсора, установленное таким образом, что он меняется на указатель при наведении на него указателя мыши.
css
style.css

body {
/* цвет фона */
background-color: lightgreen;
/* Плавный переход цвета фона */
transition: background-color .5s;
}
/* Использование flex с направлением столбца для выравнивания элементов по вертикали */
.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%;
}
/* Изменение размеров шрифта на подходящие */
.now-playing {
font-size: 1rem;
}
.track-name {
font-size: 3rem;
}
.track-artist {
font-size: 1.5rem;
}
/* Использование flex с направлением строки для выравнивания элементов в горизонтальном направлении */
.buttons {
display: flex;
flex-direction: row;
align-items: center;
}
.playpause-track, .prev-track, .next-track {
padding: 25px;
opacity: 0.8;
/* Плавный переход непрозрачности */
transition: opacity .2s;
}
/* Изменить непрозрачность при наведении мыши */
.playpause-track:hover, .prev-track:hover, .next-track:hover {
opacity: 1.0;
}
/* Определяем ширину ползунка, чтобы он правильно масштабировался */
.slider_container {
width: 75%;
max-width: 400px;
display: flex;
justify-content: center;
align-items: center;
}
/* Изменить внешний вид 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;
}
/* Изменяем внешний вид бегунка ползунка */
.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%;
}
/* Изменить непрозрачность при наведении мыши */
.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;
}
/* Изменяем курсор мыши на указатель при наведении */
i.fa-play-circle, i.fa-pause-circle, i.fa-step-forward, i.fa-step-backward {
cursor: pointer;
}

Логика Simple Music Player:
Логика плеера определяется в файле JavaScript. Есть несколько функций, которые работают вместе, чтобы управлять всеми функциями плеера.
Шаг 1: Определение всех переменных и доступ к элементам HTML 
. Необходимые элементы макета HTML, которые должны быть динамически изменены, сначала выбираются с помощью метода querySelector(). Затем им присваиваются имена переменных, чтобы к ним можно было получить доступ и изменить их. Также определяются другие переменные, к которым будет осуществляться доступ на протяжении всей программы.
JavaScript
main.js

// Выбираем все элементы на HTML-странице
// и присвоить их переменной
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");

// Указываем глобально используемые значения
let track_index = 0;
let isPlaying = false;
let updateTimer;

// Создаём аудио элемент для плеера
let curr_track = document.createElement('audio');

// Определяем список треков, которые должны быть воспроизведены
let track_list = [
{
name: "igra-prestolov--3-sezon-4-seriya-konec",
artist: "неизвестно",
image: "Image URL",
path: "mp3/igra-prestolov--3-sezon-4-seriya-konec.mp3"
},
{
name: "igra-prestolov-drakaris",
artist: "неизвестно",
image: "Image URL",
path: "mp3/igra-prestolov-drakaris.mp3"
},
{
name: "igra-prestolov-osnovnaya-tema-veolonchel",
artist: "неизвестно",
image: "Image URL",
path: "mp3/igra-prestolov-osnovnaya-tema-veolonchel.mp3",
},
];

Шаг 2: Загрузка нового трека из списка
Все треки, которые необходимо воспроизвести, определяются в списке треков как объекты. Эти объекты содержат такие свойства, как имя, исполнитель, изображение и путь к треку. После этого к каждому треку можно получить доступ, используя его индекс трека.
Для загрузки трека определена функция loadTrack(), которая обрабатывает следующие вещи: 
 
• Сброс всех значений предыдущего трека
Создается функция resetValues(), которая обрабатывает сброс значения длительности ползунка к их начальным значениям перед началом нового трека. Это предотвращает скачки ползунка поиска во время загрузки нового трека.
• Загрузка трека
Элементу audio назначается новый источник с помощью его свойства src. Ему может быть задан любой путь из файловой системы или URL. Затем метод load() используется для аудиоэлемента, чтобы подготовить трек.
• Обновление отображаемой 
обложки трека. Обложка трека извлекается из массива и назначается с помощью свойства backgroundImage.
• Обновление деталей трека для отображения 
Детали трека извлекаются из массива и назначаются с помощью свойства textContent.
• Добавление прослушивателей событий к треку
К элементу мультимедиа добавлено два прослушивателя событий, первый для обновления текущей позиции ползунка длительности, а второй — для загрузки следующего трека после завершения текущего трека.
• Установка случайного цветного фона 
Цветной фон создается путем рандомизации используемых значений красного, зеленого и синего и установки его в качестве цвета. Эффект анимируется с помощью свойства перехода цвета фона.

function loadTrack(track_index) {
// Очистить предыдущий таймер ползунка длительности
clearInterval(updateTimer);
resetValues();

// Загрузить новый трек
curr_track.src = track_list[track_index].path;
curr_track.load();

// Обновить информацию о треке
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;

// Устанавливаем интервал 1000 миллисекунд
// для обновления ползунка длительности
updateTimer = setInterval(seekUpdate, 1000);

// Перейти к следующему треку, если текущий закончил воспроизведение
// используя событие "завершено"
curr_track.addEventListener("ended", nextTrack);

// Применить случайный цвет фона
random_bg_color();
}

function random_bg_color() {
// Получить случайное число от 64 до 256
// (для получения более светлых тонов)
let red = Math.floor(Math.random() * 256) + 64;
let green = Math.floor(Math.random() * 256) + 64;
let blue = Math.floor(Math.random() * 256) + 64;

// Построить цвет с заданными значениями
let bgColor = "rgb(" + red + ", " + green + ", " + blue + ")";

// Установить фон на новый цвет
document.body.style.background = bgColor;
}

// Функция для сброса всех значений по умолчанию
function resetValues() {
curr_time.textContent = "00:00";
total_duration.textContent = "00:00";
seek_slider.value = 0;
}

Шаг 3: Настройка кнопок проигрывателя 
Функция playTrack() управляет воспроизведением текущего загруженного трека. Для этой функции используется метод play() API HTMLMediaElement. Значок кнопки также изменится на значок паузы. Это делается с помощью одного из значков из библиотеки FontAwesome и вставки его с помощью innerHTML.
Функция pauseTrack() управляет воспроизведением текущей загруженного трека. Для этой функции используется метод pause() API HTMLMediaElement. Значок кнопки также меняется обратно на значок воспроизведения. Это делается с помощью одного из значков из библиотеки FontAwesome и вставки его с помощью innerHTML.
Эти две функции вызываются в зависимости от того, воспроизводится трек в данный момент или нет. Функция playpause() обрабатывает фактическое управление воспроизведением/паузой трека.
Функция prevTrack() обрабатывает загрузку предыдущего трека и перемещение индекса назад. Индекс сбрасывается на последний трек, когда индекс достигает первого трека. Определенный выше метод loadTrack() используется для загрузки нового трека.
Точно так же функция nextTrack() обрабатывает загрузку следующего трека и перемещение индекса вперед. Индекс сбрасывается на первый трек, когда индекс достигает последнего трека. Определенный выше метод loadTrack() используется для загрузки нового трека.

function playpauseTrack() {
// Переключение между воспроизведением и паузой
// в зависимости от текущего состояния
if (!isPlaying) playTrack();
else pauseTrack();
}

function playTrack() {
// Воспроизвести загруженный трек
curr_track.play();
isPlaying = true;

// Заменить значок воспроизведения на значок паузы
playpause_btn.innerHTML = '<i class="fa fa-pause-circle fa-5x"></i>';
}

function pauseTrack() {
// Приостановить загруженный трек
curr_track.pause();
isPlaying = false;

// Заменить значок паузы на значок воспроизведения
playpause_btn.innerHTML = '<i class="fa fa-play-circle fa-5x"></i>';
}

function nextTrack() {
// Вернитесь к первому треку, если
// текущий является последним в списке треков
if (track_index < track_list.length - 1)
track_index += 1;
else track_index = 0;

// Загрузите и воспроизведите новый трек
loadTrack(track_index);
playTrack();
}

function prevTrack() {
// Вернитесь к последнему треку, если
// текущий первый в списке треков
if (track_index > 0)
track_index -= 1;
else track_index = track_list.length - 1;

// Загрузите и воспроизведите новый трек
loadTrack(track_index);
playTrack();
}

Шаг 4: Настройка части ползунков
Мы настроим два ползунка, которые управляют ползунком длительности и ползунком громкости.
 
• Ползунок длительности
Ползунок длительности показывает текущую позицию воспроизведения на ползунке, обновляя его текущим временем дорожки. Создана новая функция seekUpdate(), которая обрабатывает обновление ползунка длительности относительно текущего времени трека. Позиция ползунка длительности вычисляется и устанавливается с помощью свойства value. 
Теперь эту функцию нужно вызывать каждый раз, когда трек продвигается дальше. Это можно сделать, запланировав его обновление каждую секунду. Это можно сделать с помощью метода setInterval() с интервалом в 1000 миллисекунд. Этот таймер сбрасывается каждый раз при загрузке нового трека.
Эта функция также обрабатывает изменение прошедшего времени и общей продолжительности трека, которая обновляется каждый раз, когда эта функция срабатывает. Минуты и секунды рассчитываются отдельно и правильно форматируются для отображения. 
 
• Ползунок громкости
Ползунок громкости используется для отображения текущего уровня громкости трека. Создана новая функция setVolume(), которая обрабатывает настройку ползунка громкости всякий раз, когда пользователь ее меняет. 

function seekTo() {
// Рассчитать позицию длительности по
// проценту ползунка длительности
// и получить относительную продолжительность трека
seekto = curr_track.duration * (seek_slider.value / 100);

// Установите текущую позицию трека на рассчитанную позицию длительности
curr_track.currentTime = seekto;
}

function setVolume() {
// Установите громкость в соответствии с
// процентом установленного ползунка громкости
curr_track.volume = volume_slider.value / 100;
}

function seekUpdate() {
let seekPosition = 0;

// Проверьте, является ли продолжительность текущего трека разборчивым числом
if (!isNaN(curr_track.duration))
{
seekPosition = curr_track.currentTime * (100 / curr_track.duration);
seek_slider.value = seekPosition;

// Рассчитать оставшееся время и общую продолжительность
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);

// Добавьте ноль к однозначным значениям времени
if (currentSeconds < 10) { currentSeconds = "0" + currentSeconds; }
if (durationSeconds < 10) { durationSeconds = "0" + durationSeconds; }
if (currentMinutes < 10) { currentMinutes = "0" + currentMinutes; }
if (durationMinutes < 10) { durationMinutes = "0" + durationMinutes; } // Показать обновленную продолжительность
curr_time.textContent = currentMinutes + ":" + currentSeconds;
total_duration.textContent = durationMinutes + ":" + durationSeconds;
}
}

Шаг 5: Запуск проигрывателя
Первый трек загружается вызовом функции loadTrack(). Это загрузит первый трек из списка треков и обновит все детали трека. Затем пользователь может начать воспроизведение трека с помощью кнопки воспроизведения. Кнопки предыдущего и следующего трека будут загружать предыдущий и следующий трек соответственно и начинать их воспроизведение.
Следующий трек загружается автоматически по окончании воспроизведения трека. Пользователь может искать позицию на треке с помощью ползунка длительности. Громкость также можно регулировать с помощью ползунка громкости.

// Загрузить первый трек в треклисте
loadTrack(track_index);

Обсуждение закрыто.