Files
music-storage/music_storage/static/js/player.js

180 lines
6.2 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
document.addEventListener('DOMContentLoaded', function () {
const audioPlayer = document.getElementById('audioPlayer');
const trackItems = document.querySelectorAll('.track-item');
const currentTrack = document.getElementById('currentTrack');
const currentArtist = document.getElementById('currentArtist');
const playerContainer = document.getElementById('playerContainer');
const playPauseBtn = document.getElementById('playPauseBtn');
const nextBtn = document.getElementById('nextBtn');
const prevBtn = document.getElementById('prevBtn');
const volumeControl = document.getElementById('volumeControl');
const savedVolume = localStorage.getItem('audioPlayerVolume');
const progressBar = document.getElementById('audioProgress');
const currentTimeElem = document.getElementById('currentTime');
const durationElem = document.getElementById('durationTime');
let currentIndex = -1;
function updateUI(title, artist) {
currentTrack.textContent = title;
currentArtist.textContent = 'Исполнитель: ' + artist;
}
function formatTime(seconds) {
const m = Math.floor(seconds / 60);
const s = Math.floor(seconds % 60);
return `${m}:${s < 10 ? '0' : ''}${s}`;
}
function updateProgressUI(current, duration) {
if (!progressBar) return;
progressBar.max = duration || 0;
progressBar.value = current || 0;
if (currentTimeElem) currentTimeElem.textContent = formatTime(current || 0);
if (durationElem) durationElem.textContent = formatTime(duration || 0);
}
// Восстановление сохраненного уровня громкости
if (savedVolume !== null) {
audioPlayer.volume = parseFloat(savedVolume);
}
// Управление громкостью
if (volumeControl) {
volumeControl.addEventListener('input', () => {
audioPlayer.volume = volumeControl.value;
});
}
// Обновление прогресса при воспроизведении
audioPlayer.addEventListener('timeupdate', () => {
updateProgressUI(audioPlayer.currentTime, audioPlayer.duration);
});
// Перемотка через прогресс-бар
if (progressBar) {
progressBar.addEventListener('input', () => {
audioPlayer.currentTime = progressBar.value;
updateProgressUI(audioPlayer.currentTime, audioPlayer.duration);
});
}
// Обновление UI после загрузки метаданных
audioPlayer.addEventListener('loadedmetadata', () => {
updateProgressUI(0, audioPlayer.duration);
});
function updateMediaSession(title, artist, coverImage) {
if (!('mediaSession' in navigator)) return;
navigator.mediaSession.metadata = new MediaMetadata({
title: title,
artist: artist,
artwork: [coverImage ? { src: coverImage, sizes: '512x512', type: 'image/png' } : null].filter(Boolean),
});
navigator.mediaSession.setActionHandler('play', () => audioPlayer.play());
navigator.mediaSession.setActionHandler('pause', () => audioPlayer.pause());
navigator.mediaSession.setActionHandler('previoustrack', () => playTrack(currentIndex - 1));
navigator.mediaSession.setActionHandler('nexttrack', () => playTrack(currentIndex + 1));
}
// ---------------------------
// Сброс активного трека
function resetActiveTrack() {
trackItems.forEach(item => {
item.classList.remove('active');
});
}
function playTrack(index) {
if (index < 0 || index >= trackItems.length) return;
currentIndex = index;
const item = trackItems[index];
const api = item.dataset.trackSrc;
fetch(api)
.then(response => response.json())
.then(data => {
const src = data.url;
const title = data.title;
const artist = data.album.artist.name;
const coverImage = data.album.cover_image;
resetActiveTrack();
item.classList.add('active');
updateUI(title, artist, coverImage);
// ---------------------------
// ВЫЗОВ Media Session API
updateMediaSession(title, artist, coverImage);
// ---------------------------
audioPlayer.src = src;
audioPlayer.title = artist + ' - ' + title;
audioPlayer.play().catch(err => console.log(err));
updatePlayButton(true);
})
.catch(err => console.log(err));
}
// Клик по треку
trackItems.forEach((item, i) => {
item.addEventListener('click', () => {
playTrack(i)
if (playerContainer.hidden) {
playerContainer.removeAttribute('hidden');
}
});
});
// Auto-next on end
audioPlayer.addEventListener('ended', () => {
playTrack(currentIndex + 1);
});
// Автоматически скрыть плеер при прокрутке
let scrollTimer;
window.addEventListener('scroll', function () {
clearTimeout(scrollTimer);
playerContainer.style.opacity = '0.75';
scrollTimer = setTimeout(() => {
playerContainer.style.opacity = '1';
}, 200);
});
function updatePlayButton(isPlaying) {
playPauseBtn.innerHTML = isPlaying
? '<i class="fas fa-pause"></i>'
: '<i class="fas fa-play"></i>';
}
playPauseBtn.addEventListener('click', () => {
if (!audioPlayer.src) return;
if (audioPlayer.paused) {
audioPlayer.play();
} else {
audioPlayer.pause();
}
});
audioPlayer.addEventListener('play', () => updatePlayButton(true));
audioPlayer.addEventListener('pause', () => updatePlayButton(false));
// Next track
nextBtn.addEventListener('click', () => {
if (currentIndex !== -1) playTrack(currentIndex + 1);
});
// Previous track
prevBtn.addEventListener('click', () => {
if (currentIndex !== -1) playTrack(currentIndex - 1);
});
});