文章最后更新时间:
逛论坛的时候发现一个美化播放器,这个播放器还是不错的,用了一下,是从从MetingAPI获取播放列表的,我觉得喜欢的可以换一下接口换成你的,接口网上很多,喜欢的自行部署吧!文章源自奇客源码-https://www.qkget.cn/6012.html
文章源自奇客源码-https://www.qkget.cn/6012.html
这款美化版本的播放器还是不错的,音乐跟着歌词同步,并且当播放音乐的时候还左下角还有封面旋转的效果!文章源自奇客源码-https://www.qkget.cn/6012.html
代码部署
[wechat2 key=dmhdzh reply=卡密]文章源自奇客源码-https://www.qkget.cn/6012.html
<style>
.meting-player-container * {
margin: 0;
padding: 0;
box-sizing: border-box;
font-family: 'Microsoft YaHei', sans-serif;
}
.meting-player-container {
position: fixed;
left: 20px;
bottom: 70px;
z-index: 1000;
width: 360px;
transition: all 0.3s ease;
}
.meting-player-container.minimized {
width: 50px;
height: 50px;
}
.meting-player-main {
background: rgba(60, 66, 64, 0.9);
border-radius: 12px;
overflow: hidden;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
color: white;
display: flex;
flex-direction: column;
transition: all 0.3s ease;
}
.minimized .meting-player-main {
height: 50px;
width: 50px;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.meting-album-cover {
display: none;
width: 40px;
height: 40px;
border-radius: 50%;
object-fit: cover;
animation: meting-rotate 10s linear infinite;
animation-play-state: paused;
}
.minimized .meting-album-cover {
display: block;
}
.playing .meting-album-cover {
animation-play-state: running;
}
@keyframes meting-rotate {
100% {
transform: rotate(360deg);
}
}
.meting-player-header {
display: flex;
align-items: center;
padding: 12px 15px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.minimized .meting-player-header {
display: none;
}
.meting-song-info {
flex: 1;
overflow: hidden;
}
.meting-song-title {
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.meting-song-artist {
font-size: 12px;
opacity: 0.8;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.meting-player-controls {
display: flex;
flex-direction: column;
padding: 15px;
}
.minimized .meting-player-controls {
display: none;
}
.meting-progress-top {
display: flex;
align-items: center;
margin-bottom: 15px;
width: 100%;
}
.meting-progress-container {
flex: 1;
height: 12px;
background: rgba(255, 255, 255, 0.3);
border-radius: 6px;
margin-right: 10px;
cursor: pointer;
position: relative;
}
.meting-progress-bar {
height: 100%;
background: #1db954;
border-radius: 6px;
width: 0%;
}
.meting-time-display {
font-size: 12px;
opacity: 0.8;
min-width: 80px;
text-align: center;
}
.meting-controls-bottom {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
}
.meting-control-buttons {
display: flex;
align-items: center;
}
.meting-control-btn {
background: none;
border: none;
color: white;
font-size: 20px;
cursor: pointer;
margin: 0 5px;
outline: none;
transition: all 0.2s;
width: 32px;
height: 32px;
display: flex;
align-items: center;
justify-content: center;
}
.meting-control-btn:hover {
color: #1db954;
}
.meting-play-pause {
font-size: 32px;
width: 40px;
height: 40px;
}
.meting-volume-container {
display: flex;
align-items: center;
}
.meting-volume-btn {
background: none;
border: none;
color: white;
font-size: 18px;
cursor: pointer;
outline: none;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.meting-volume-slider {
width: 80px;
margin-left: 5px;
-webkit-appearance: none;
height: 4px;
background: rgba(255, 255, 255, 0.3);
border-radius: 2px;
outline: none;
}
.meting-volume-slider::-webkit-slider-thumb {
-webkit-appearance: none;
width: 12px;
height: 12px;
border-radius: 50%;
background: #fff;
cursor: pointer;
}
.meting-toggle-player {
position: absolute;
top: -10px;
right: -10px;
width: 24px;
height: 24px;
border-radius: 50%;
background: #1db954;
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
border: none;
font-size: 14px;
transition: all 0.2s;
}
.meting-toggle-player:hover {
transform: scale(1.1);
}
.meting-lyrics-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
text-align: center;
padding: 10px;
background: rgba(0, 0, 0, 0.5);
color: white;
font-size: 16px;
z-index: 900;
transition: all 0.3s;
}
.meting-lyrics-line {
margin: 5px 0;
opacity: 0.5;
transition: all 0.3s;
}
.meting-lyrics-line.active {
opacity: 1;
color: #1db954;
font-weight: bold;
transform: scale(1.05);
}
.meting-playlist-btn {
background: none;
border: none;
color: white;
font-size: 20px;
cursor: pointer;
margin-left: 10px;
outline: none;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
.meting-lyrics-btn {
background: none;
border: none;
color: white;
font-size: 16px;
cursor: pointer;
margin-left: 10px;
outline: none;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
}
.meting-lyrics-btn.active {
color: #1db954;
}
/* 重新设计播放列表样式 - 更美观的电脑端播放列表 */
.meting-playlist-container {
position: absolute;
bottom: calc(100% + 10px); /* 与控制面板之间添加间隙 */
left: 0;
right: 0;
background: rgba(60, 66, 64, 0.9); /* 透明度与控制台一致 */
backdrop-filter: blur(10px);
border-radius: 12px; /* 四个角都是圆角 */
max-height: 400px;
overflow-y: auto;
display: none;
padding: 15px;
box-shadow: 0 -5px 25px rgba(0, 0, 0, 0.4);
border: 1px solid rgba(255, 255, 255, 0.1);
scrollbar-width: thin;
scrollbar-color: #1db954 rgba(255, 255, 255, 0.1);
}
.meting-playlist-container::-webkit-scrollbar {
width: 6px;
}
.meting-playlist-container::-webkit-scrollbar-track {
background: rgba(255, 255, 255, 0.05);
border-radius: 3px;
}
.meting-playlist-container::-webkit-scrollbar-thumb {
background-color: #1db954;
border-radius: 3px;
}
.meting-playlist-container.show {
display: block;
}
.meting-playlist-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.meting-playlist-title {
font-size: 16px;
font-weight: bold;
color: #fff;
}
.meting-playlist-count {
font-size: 13px;
opacity: 0.7;
}
.meting-playlist-items {
display: flex;
flex-direction: column;
gap: 8px;
}
.meting-playlist-item {
padding: 12px 15px;
border-radius: 8px;
cursor: pointer;
display: flex;
align-items: center;
transition: all 0.2s ease;
background: rgba(255, 255, 255, 0.03);
}
.meting-playlist-item:hover {
background: rgba(29, 185, 84, 0.15);
transform: translateY(-2px);
}
.meting-playlist-item.playing {
background: rgba(29, 185, 84, 0.2);
box-shadow: 0 4px 12px rgba(29, 185, 84, 0.2);
}
.meting-playlist-item.playing .meting-playlist-item-index {
color: #1db954;
font-weight: bold;
}
.meting-playlist-item.playing .meting-playlist-item-title {
color: #1db954;
}
.meting-playlist-item-index {
margin-right: 15px;
font-size: 14px;
opacity: 0.8;
min-width: 24px;
text-align: center;
transition: all 0.2s ease;
}
.meting-playlist-item-info {
flex: 1;
overflow: hidden;
min-width: 0;
}
.meting-playlist-item-title {
font-size: 14px;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 3px;
transition: all 0.2s ease;
}
.meting-playlist-item-artist {
font-size: 12px;
opacity: 0.7;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.meting-playlist-item-duration {
font-size: 12px;
opacity: 0.6;
margin-left: 10px;
min-width: 40px;
text-align: right;
}
.meting-mode-btn {
background: none;
border: none;
color: white;
font-size: 16px;
cursor: pointer;
margin-left: 5px;
outline: none;
width: 24px;
height: 24px;
display: flex;
align-items: center;
justify-content: center;
}
/* 手机端适配 */
@media screen and (max-width: 768px) {
.meting-player-container {
left: 10px;
right: auto;
bottom: 20px;
width: auto;
max-width: 320px;
margin: 0;
}
.meting-player-main {
border-radius: 10px;
}
.meting-player-header {
padding: 10px;
}
.meting-song-title {
font-size: 13px;
}
.meting-song-artist {
font-size: 11px;
}
.meting-player-controls {
padding: 10px;
}
.meting-progress-top {
flex-direction: row;
align-items: center;
margin-bottom: 10px;
}
.meting-time-display {
margin-top: 0;
min-width: auto;
text-align: right;
font-size: 11px;
margin-left: 10px;
}
.meting-controls-bottom {
flex-direction: row;
gap: 5px;
}
.meting-volume-container {
width: auto;
justify-content: flex-end;
}
.meting-volume-slider {
flex: 1;
max-width: 80px;
}
.meting-control-btn {
font-size: 18px;
margin: 0 3px;
width: 28px;
height: 28px;
}
.meting-play-pause {
font-size: 28px;
width: 36px;
height: 36px;
}
.meting-toggle-player {
top: -8px;
right: -8px;
width: 20px;
height: 20px;
font-size: 12px;
}
.meting-lyrics-container {
font-size: 14px;
padding: 8px;
z-index: 800;
}
/* 手机端播放列表样式 */
.meting-playlist-container {
max-height: 200px;
border-radius: 10px; /* 四个角都是圆角 */
padding: 10px;
bottom: calc(100% + 8px); /* 与控制面板之间添加间隙 */
background: rgba(60, 66, 64, 0.9); /* 透明度与控制台一致 */
}
.meting-playlist-header {
margin-bottom: 10px;
padding-bottom: 8px;
}
.meting-playlist-title {
font-size: 14px;
}
.meting-playlist-count {
font-size: 11px;
}
.meting-playlist-item {
padding: 10px 12px;
border-radius: 6px;
}
.meting-playlist-item-index {
margin-right: 12px;
font-size: 12px;
min-width: 20px;
}
.meting-playlist-item-title {
font-size: 13px;
}
.meting-playlist-item-artist {
font-size: 11px;
}
.meting-playlist-item-duration {
font-size: 11px;
min-width: 35px;
}
.meting-lyrics-container:not([style*="display: none"]) {
height: auto;
}
.meting-lyrics-container[style*="display: none"] ~ .meting-player-container {
bottom: 10px;
}
}
/* 小屏手机适配 */
@media screen and (max-width: 480px) {
.meting-player-container {
left: 5px;
right: auto;
bottom: 10px;
max-width: 300px;
}
.meting-player-header {
padding: 8px;
}
.meting-song-title {
font-size: 12px;
}
.meting-song-artist {
font-size: 10px;
}
.meting-control-btn {
font-size: 16px;
margin: 0 2px;
width: 24px;
height: 24px;
}
.meting-play-pause {
font-size: 24px;
width: 32px;
height: 32px;
}
.meting-lyrics-btn,
.meting-playlist-btn,
.meting-mode-btn {
font-size: 16px;
margin-left: 5px;
width: 20px;
height: 20px;
}
.meting-time-display {
font-size: 10px;
}
.meting-lyrics-container {
font-size: 13px;
padding: 5px;
}
.meting-volume-slider {
max-width: 60px;
}
/* 小屏手机播放列表样式 */
.meting-playlist-container {
max-height: 180px;
padding: 8px;
bottom: calc(100% + 5px); /* 与控制面板之间添加间隙 */
border-radius: 8px; /* 四个角都是圆角 */
background: rgba(60, 66, 64, 0.9); /* 透明度与控制台一致 */
}
.meting-playlist-item {
padding: 8px 10px;
}
.meting-playlist-item-index {
margin-right: 10px;
font-size: 11px;
min-width: 18px;
}
.meting-playlist-item-title {
font-size: 12px;
}
.meting-playlist-item-artist {
font-size: 10px;
}
.meting-playlist-item-duration {
display: none;
}
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<div class="meting-player-container">
<div class="meting-player-main">
<img class="meting-album-cover" src="" alt="专辑封面">
<div class="meting-player-header">
<div class="meting-song-info">
<div class="meting-song-title">正在加载...</div>
<div class="meting-song-artist">请稍候</div>
</div>
<button class="meting-lyrics-btn">词</button>
<button class="meting-playlist-btn"><i class="fa fa-list"></i></button>
<button class="meting-mode-btn"><i class="fa fa-random"></i></button>
</div>
<div class="meting-player-controls">
<div class="meting-progress-top">
<div class="meting-progress-container">
<div class="meting-progress-bar"></div>
</div>
<div class="meting-time-display">00:00 / 00:00</div>
</div>
<div class="meting-controls-bottom">
<div class="meting-control-buttons">
<button class="meting-control-btn meting-prev-btn"><i class="fa fa-step-backward"></i></button>
<button class="meting-control-btn meting-play-pause"><i class="fa fa-play"></i></button>
<button class="meting-control-btn meting-next-btn"><i class="fa fa-step-forward"></i></button>
</div>
<div class="meting-volume-container">
<button class="meting-volume-btn"><i class="fa fa-volume-up"></i></button>
<input type="range" class="meting-volume-slider" min="0" max="100" value="80">
</div>
</div>
</div>
<div class="meting-playlist-container">
<div class="meting-playlist-header">
<div class="meting-playlist-title">播放列表</div>
<div class="meting-playlist-count">0 首歌曲</div>
</div>
<div class="meting-playlist-items"></div>
</div>
</div>
<button class="meting-toggle-player"><i class="fa fa-minus"></i></button>
</div>
<div class="meting-lyrics-container">
<div class="meting-lyrics-line">歌词加载中...</div>
</div>
<script>
(function () {
// 播放器状态
const playerState = {
playlist: [],
currentIndex: 0,
isPlaying: false,
volume: 80,
currentTime: 0,
duration: 0,
mode: 'random', // random, sequential, loop
minimized: false,
lyricsVisible: true,
lyricsAutoHide: true,
lastPlayedSong: null,
lastPlayedPosition: 0,
autoPlayBlocked: false
};
// DOM元素
const elements = {
playerContainer: document.querySelector('.meting-player-container'),
playerMain: document.querySelector('.meting-player-main'),
albumCover: document.querySelector('.meting-album-cover'),
songTitle: document.querySelector('.meting-song-title'),
songArtist: document.querySelector('.meting-song-artist'),
playPauseBtn: document.querySelector('.meting-play-pause'),
prevBtn: document.querySelector('.meting-prev-btn'),
nextBtn: document.querySelector('.meting-next-btn'),
progressContainer: document.querySelector('.meting-progress-container'),
progressBar: document.querySelector('.meting-progress-bar'),
timeDisplay: document.querySelector('.meting-time-display'),
volumeBtn: document.querySelector('.meting-volume-btn'),
volumeSlider: document.querySelector('.meting-volume-slider'),
togglePlayerBtn: document.querySelector('.meting-toggle-player'),
lyricsContainer: document.querySelector('.meting-lyrics-container'),
lyricsLine: document.querySelector('.meting-lyrics-line'),
playlistBtn: document.querySelector('.meting-playlist-btn'),
playlistContainer: document.querySelector('.meting-playlist-container'),
playlistItems: document.querySelector('.meting-playlist-items'),
playlistTitle: document.querySelector('.meting-playlist-title'),
playlistCount: document.querySelector('.meting-playlist-count'),
modeBtn: document.querySelector('.meting-mode-btn'),
lyricsBtn: document.querySelector('.meting-lyrics-btn')
};
// 音频元素
const audio = new Audio();
audio.volume = playerState.volume / 100;
// 从localStorage加载状态
function loadPlayerState() {
const savedState = localStorage.getItem('metingPlayerState');
if (savedState) {
const state = JSON.parse(savedState);
playerState.currentIndex = state.currentIndex || 0;
playerState.isPlaying = state.isPlaying || false;
playerState.volume = state.volume || 80;
playerState.currentTime = state.currentTime || 0;
playerState.mode = state.mode || 'random';
playerState.minimized = state.minimized || false;
playerState.lyricsVisible = state.lyricsVisible !== undefined ? state.lyricsVisible : true;
playerState.lyricsAutoHide = state.lyricsAutoHide !== undefined ? state.lyricsAutoHide : true;
playerState.lastPlayedSong = state.lastPlayedSong || null;
playerState.lastPlayedPosition = state.lastPlayedPosition || 0;
// 应用保存的状态
audio.volume = playerState.volume / 100;
elements.volumeSlider.value = playerState.volume;
if (playerState.minimized) {
elements.playerContainer.classList.add('minimized');
elements.togglePlayerBtn.innerHTML = '<i class="fa fa-plus"></i>';
}
// 应用歌词显示状态
updateLyricsVisibility();
updateLyricsButton();
updateModeButton();
updateVolumeIcon();
}
}
// 保存状态到localStorage
function savePlayerState() {
playerState.currentTime = audio.currentTime;
if (playerState.playlist.length > 0 && playerState.currentIndex >= 0) {
const currentSong = playerState.playlist[playerState.currentIndex];
playerState.lastPlayedSong = {
id: currentSong.id || currentSong.name,
name: currentSong.name,
artist: currentSong.artist
};
playerState.lastPlayedPosition = audio.currentTime;
}
localStorage.setItem('metingPlayerState', JSON.stringify(playerState));
}
// 更新歌词按钮状态
function updateLyricsButton() {
if (playerState.lyricsVisible) {
elements.lyricsBtn.classList.add('active');
} else {
elements.lyricsBtn.classList.remove('active');
}
}
// 更新歌词可见性
function updateLyricsVisibility() {
if (playerState.lyricsVisible && !playerState.autoPlayBlocked) {
elements.lyricsContainer.style.display = 'block';
adjustPlayerPosition();
} else {
elements.lyricsContainer.style.display = 'none';
resetPlayerPosition();
}
}
// 调整播放器位置(确保在歌词上方)
function adjustPlayerPosition() {
if (window.matchMedia('(max-width: 768px)').matches) {
const lyricsHeight = elements.lyricsContainer.offsetHeight;
elements.playerContainer.style.bottom = (lyricsHeight + 10) + 'px';
}
}
// 重置播放器位置(歌词隐藏时)
function resetPlayerPosition() {
if (window.matchMedia('(max-width: 768px)').matches) {
elements.playerContainer.style.bottom = '10px';
}
}
// 更新模式按钮
function updateModeButton() {
switch (playerState.mode) {
case 'random':
elements.modeBtn.innerHTML = '<i class="fa fa-random"></i>';
break;
case 'sequential':
elements.modeBtn.innerHTML = '<i class="fa fa-arrow-right"></i>';
break;
case 'loop':
elements.modeBtn.innerHTML = '<i class="fa fa-repeat"></i>';
break;
}
}
// 更新音量图标
function updateVolumeIcon() {
const volume = elements.volumeSlider.value;
let iconClass = 'fa-volume-up';
if (volume == 0) {
iconClass = 'fa-volume-off';
} else if (volume < 33) {
iconClass = 'fa-volume-down';
}
elements.volumeBtn.innerHTML = `<i class="fa ${iconClass}"></i>`;
}
// 从MetingAPI获取播放列表
async function fetchPlaylist() {
try {
const response = await fetch('https://music.3e0.cn/?server=netease&type=playlist&id=701613649');
const playlist = await response.json();
if (Array.isArray(playlist) && playlist.length > 0) {
playerState.playlist = playlist;
renderPlaylist();
// 检查是否有上次播放的歌曲记录
let targetIndex = 0;
let targetPosition = 0;
if (playerState.lastPlayedSong) {
// 尝试找到上次播放的歌曲
const foundIndex = playlist.findIndex(song =>
(song.id && song.id === playerState.lastPlayedSong.id) ||
(song.name === playerState.lastPlayedSong.name && song.artist === playerState.lastPlayedSong.artist)
);
if (foundIndex !== -1) {
targetIndex = foundIndex;
targetPosition = playerState.lastPlayedPosition;
}
} else if (playerState.currentIndex >= 0 && playerState.currentIndex < playlist.length) {
// 使用保存的索引
targetIndex = playerState.currentIndex;
targetPosition = playerState.currentTime;
}
// 加载歌曲
loadSong(targetIndex, targetPosition);
// 如果是播放状态,开始播放
if (playerState.isPlaying) {
setTimeout(() => {
audio.play().catch(e => {
console.log('自动播放被阻止:', e);
playerState.autoPlayBlocked = true;
playerState.isPlaying = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';
elements.playerMain.classList.remove('playing');
// 自动播放被阻止时隐藏歌词
updateLyricsVisibility();
savePlayerState();
});
}, 500);
}
} else {
console.error('获取播放列表失败');
elements.songTitle.textContent = '获取播放列表失败';
}
} catch (error) {
console.error('获取播放列表出错:', error);
elements.songTitle.textContent = '获取播放列表出错';
}
}
// 渲染播放列表
function renderPlaylist() {
elements.playlistItems.innerHTML = '';
elements.playlistCount.textContent = `${playerState.playlist.length} 首歌曲`;
playerState.playlist.forEach((song, index) => {
const item = document.createElement('div');
item.className = 'meting-playlist-item';
if (index === playerState.currentIndex) {
item.classList.add('playing');
}
// 格式化歌曲时长
let durationText = '';
if (song.duration) {
const minutes = Math.floor(song.duration / 60);
const seconds = Math.floor(song.duration % 60);
durationText = `${minutes}:${seconds.toString().padStart(2, '0')}`;
}
item.innerHTML = `
<div class="meting-playlist-item-index">${index + 1}</div>
<div class="meting-playlist-item-info">
<div class="meting-playlist-item-title">${song.name}</div>
<div class="meting-playlist-item-artist">${song.artist}</div>
</div>
<div class="meting-playlist-item-duration">${durationText}</div>
`;
// 修改播放列表项点击事件处理 - 修复歌词显示问题
item.addEventListener('click', () => {
// 设置播放状态为true
playerState.isPlaying = true;
// 更新播放按钮状态
elements.playPauseBtn.innerHTML = '<i class="fa fa-pause"></i>';
elements.playerMain.classList.add('playing');
// 确保歌词正确显示 - 修复的关键代码
playerState.autoPlayBlocked = false;
updateLyricsVisibility();
// 加载并播放歌曲
loadSong(index);
audio.play().catch(e => {
console.log('播放被阻止:', e);
playerState.autoPlayBlocked = true;
playerState.isPlaying = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';
elements.playerMain.classList.remove('playing');
// 播放被阻止时隐藏歌词
updateLyricsVisibility();
savePlayerState();
});
});
elements.playlistItems.appendChild(item);
});
// 如果播放列表显示,自动滚动到当前播放的歌曲
if (elements.playlistContainer.classList.contains('show')) {
scrollToCurrentSong();
}
}
// 滚动到当前播放的歌曲
function scrollToCurrentSong() {
const currentItem = elements.playlistItems.children[playerState.currentIndex];
if (currentItem) {
currentItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
}
// 加载歌曲
function loadSong(index, position = 0) {
if (index < 0 || index >= playerState.playlist.length) return;
const song = playerState.playlist[index];
playerState.currentIndex = index;
elements.songTitle.textContent = song.name;
elements.songArtist.textContent = song.artist;
// 设置专辑封面 - 使用API返回的pic字段
if (song.pic) {
elements.albumCover.src = song.pic;
}
audio.src = song.url;
audio.load();
// 设置播放位置
audio.onloadedmetadata = function () {
if (position > 0 && position < audio.duration) {
audio.currentTime = position;
playerState.currentTime = position;
}
if (playerState.isPlaying) {
audio.play().catch(e => {
console.log('播放被阻止:', e);
playerState.autoPlayBlocked = true;
playerState.isPlaying = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';
elements.playerMain.classList.remove('playing');
// 播放被阻止时隐藏歌词
updateLyricsVisibility();
savePlayerState();
});
elements.playerMain.classList.add('playing');
} else {
elements.playerMain.classList.remove('playing');
}
};
// 加载歌词
fetchLyrics(song.lrc);
// 更新播放列表高亮
const items = document.querySelectorAll('.meting-playlist-item');
items.forEach((item, i) => {
if (i === index) {
item.classList.add('playing');
} else {
item.classList.remove('playing');
}
});
// 自动滚动到当前播放的歌曲
scrollToCurrentSong();
// 保存状态
savePlayerState();
// 确保歌词显示状态正确 - 新增的修复代码
updateLyricsVisibility();
}
// 获取歌词
async function fetchLyrics(url) {
try {
const response = await fetch(url);
const text = await response.text();
parseLyrics(text);
} catch (error) {
console.error('获取歌词失败:', error);
elements.lyricsLine.textContent = '歌词加载失败';
}
}
// 解析歌词
function parseLyrics(text) {
const lines = text.split('\n');
const lyrics = [];
// 解析歌词行
const regex = /\[(\d+):(\d+)\.(\d+)\](.*)/;
lines.forEach(line => {
const match = line.match(regex);
if (match) {
const minutes = parseInt(match[1]);
const seconds = parseInt(match[2]);
const milliseconds = parseInt(match[3]);
const text = match[4].trim();
const time = minutes * 60 + seconds + milliseconds / 100;
lyrics.push({ time, text });
}
});
// 按时间排序
lyrics.sort((a, b) => a.time - b.time);
// 存储歌词
playerState.lyrics = lyrics;
elements.lyricsLine.textContent = lyrics.length > 0 ? lyrics[0].text : '暂无歌词';
// 歌词加载后调整播放器位置
setTimeout(adjustPlayerPosition, 100);
}
// 更新歌词显示
function updateLyrics() {
if (!playerState.lyrics || !playerState.lyricsVisible || playerState.autoPlayBlocked) return;
const currentTime = audio.currentTime;
let currentLine = '';
for (let i = playerState.lyrics.length - 1; i >= 0; i--) {
if (currentTime >= playerState.lyrics[i].time) {
currentLine = playerState.lyrics[i].text;
break;
}
}
elements.lyricsLine.textContent = currentLine || '?';
}
// 播放/暂停
function togglePlay() {
if (audio.paused) {
audio.play().then(() => {
playerState.isPlaying = true;
playerState.autoPlayBlocked = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-pause"></i>';
elements.playerMain.classList.add('playing');
// 播放时显示歌词
updateLyricsVisibility();
}).catch(e => {
console.log('播放被阻止:', e);
playerState.autoPlayBlocked = true;
playerState.isPlaying = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';
elements.playerMain.classList.remove('playing');
// 播放被阻止时隐藏歌词
updateLyricsVisibility();
});
} else {
audio.pause();
playerState.isPlaying = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';
elements.playerMain.classList.remove('playing');
// 暂停时自动隐藏歌词
if (playerState.lyricsAutoHide && playerState.lyricsVisible) {
elements.lyricsContainer.style.display = 'none';
resetPlayerPosition();
}
}
savePlayerState();
}
// 切换歌词显示/隐藏
function toggleLyrics() {
playerState.lyricsVisible = !playerState.lyricsVisible;
updateLyricsVisibility();
updateLyricsButton();
savePlayerState();
}
// 下一首 - 修复播放状态问题
function nextSong() {
let nextIndex;
switch (playerState.mode) {
case 'random':
nextIndex = Math.floor(Math.random() * playerState.playlist.length);
break;
case 'sequential':
nextIndex = (playerState.currentIndex + 1) % playerState.playlist.length;
break;
case 'loop':
nextIndex = playerState.currentIndex;
break;
}
// 设置播放状态并更新UI - 修复的关键代码
playerState.isPlaying = true;
playerState.autoPlayBlocked = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-pause"></i>';
elements.playerMain.classList.add('playing');
// 确保歌词显示
updateLyricsVisibility();
// 加载并播放歌曲
loadSong(nextIndex);
audio.play().catch(e => {
console.log('播放被阻止:', e);
playerState.autoPlayBlocked = true;
playerState.isPlaying = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';
elements.playerMain.classList.remove('playing');
// 播放被阻止时隐藏歌词
updateLyricsVisibility();
savePlayerState();
});
}
// 上一首 - 修复播放状态问题
function prevSong() {
let prevIndex;
switch (playerState.mode) {
case 'random':
prevIndex = Math.floor(Math.random() * playerState.playlist.length);
break;
case 'sequential':
prevIndex = (playerState.currentIndex - 1 + playerState.playlist.length) % playerState.playlist.length;
break;
case 'loop':
prevIndex = playerState.currentIndex;
break;
}
// 设置播放状态并更新UI - 修复的关键代码
playerState.isPlaying = true;
playerState.autoPlayBlocked = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-pause"></i>';
elements.playerMain.classList.add('playing');
// 确保歌词显示
updateLyricsVisibility();
// 加载并播放歌曲
loadSong(prevIndex);
audio.play().catch(e => {
console.log('播放被阻止:', e);
playerState.autoPlayBlocked = true;
playerState.isPlaying = false;
elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';
elements.playerMain.classList.remove('playing');
// 播放被阻止时隐藏歌词
updateLyricsVisibility();
savePlayerState();
});
}
// 切换播放模式
function toggleMode() {
const modes = ['random', 'sequential', 'loop'];
const currentIndex = modes.indexOf(playerState.mode);
playerState.mode = modes[(currentIndex + 1) % modes.length];
updateModeButton();
savePlayerState();
}
// 切换播放器最小化状态
function toggleMinimize() {
playerState.minimized = !playerState.minimized;
if (playerState.minimized) {
elements.playerContainer.classList.add('minimized');
elements.togglePlayerBtn.innerHTML = '<i class="fa fa-plus"></i>';
// 隐藏播放列表
elements.playlistContainer.classList.remove('show');
} else {
elements.playerContainer.classList.remove('minimized');
elements.togglePlayerBtn.innerHTML = '<i class="fa fa-minus"></i>';
}
savePlayerState();
}
// 切换播放列表显示
function togglePlaylist() {
// 如果正在最小化状态,先退出最小化
if (playerState.minimized) {
toggleMinimize();
}
elements.playlistContainer.classList.toggle('show');
// 如果播放列表显示,则滚动到当前播放的歌曲
if (elements.playlistContainer.classList.contains('show')) {
// 使用setTimeout确保播放列表渲染完成
setTimeout(() => {
scrollToCurrentSong();
}, 0);
}
}
// 更新进度条
function updateProgress() {
const percent = (audio.currentTime / audio.duration) * 100;
elements.progressBar.style.width = `${percent}%`;
const currentMinutes = Math.floor(audio.currentTime / 60);
const currentSeconds = Math.floor(audio.currentTime % 60);
const durationMinutes = Math.floor(audio.duration / 60);
const durationSeconds = Math.floor(audio.duration % 60);
elements.timeDisplay.textContent =
`${currentMinutes.toString().padStart(2, '0')}:${currentSeconds.toString().padStart(2, '0')} / ${durationMinutes.toString().padStart(2, '0')}:${durationSeconds.toString().padStart(2, '0')}`;
updateLyrics();
// 定期保存播放状态(每5秒)
if (Math.floor(audio.currentTime) % 5 === 0) {
savePlayerState();
}
}
// 设置进度
function setProgress(e) {
const width = elements.progressContainer.clientWidth;
const clickX = e.offsetX;
const duration = audio.duration;
audio.currentTime = (clickX / width) * duration;
savePlayerState();
}
// 设置音量
function setVolume() {
const volume = elements.volumeSlider.value;
audio.volume = volume / 100;
playerState.volume = volume;
updateVolumeIcon();
savePlayerState();
}
// 初始化事件监听
function initEventListeners() {
elements.playPauseBtn.addEventListener('click', togglePlay);
elements.prevBtn.addEventListener('click', prevSong);
elements.nextBtn.addEventListener('click', nextSong);
elements.progressContainer.addEventListener('click', setProgress);
elements.volumeSlider.addEventListener('input', setVolume);
elements.togglePlayerBtn.addEventListener('click', toggleMinimize);
elements.lyricsBtn.addEventListener('click', toggleLyrics);
elements.playlistBtn.addEventListener('click', togglePlaylist);
elements.modeBtn.addEventListener('click', toggleMode);
audio.addEventListener('timeupdate', updateProgress);
audio.addEventListener('ended', nextSong);
// 页面关闭前保存状态
window.addEventListener('beforeunload', savePlayerState);
// 页面可见性变化时保存状态
document.addEventListener('visibilitychange', function () {
if (document.hidden) {
savePlayerState();
}
});
// 窗口大小变化时调整播放器位置
window.addEventListener('resize', function () {
if (playerState.lyricsVisible && !playerState.autoPlayBlocked) {
adjustPlayerPosition();
} else {
resetPlayerPosition();
}
});
}
// 初始化播放器
function initPlayer() {
loadPlayerState();
initEventListeners();
fetchPlaylist();
}
// 启动播放器
initPlayer();
})();
</script>[/wechat2]文章源自奇客源码-https://www.qkget.cn/6012.html
© 版权声明
网站名称:奇客源码
本文链接:
版权声明:知识共享署名-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)协议进行许可
本站资源仅供个人学习交流,转载时请以超链接形式标明文章原始出处,(如有侵权联系删除)
本文链接:
版权声明:知识共享署名-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)协议进行许可
本站资源仅供个人学习交流,转载时请以超链接形式标明文章原始出处,(如有侵权联系删除)
本站代码模板仅供学习交流使用请勿商业运营,严禁从事违法,侵权等任何非法活动,否则后果自负!
THE END
















子比主题美化
精品源码资源


暂无评论内容