注册时间2024-11-22
最后登录2025-12-9
在线时间1297 小时
UID1
买家信用
卖家信用
风云·优秀版主
|
资源无需等待,交易就趁现在,全面资源整合网络大咖云集,让你轻松玩转互联网!
您需要 登录 才可以下载或查看,没有账号?立即注册
×
腾飞博客逛论坛的时候发现一个美化播放器,这个播放器还是不错的,腾飞博客用了一下,是从从MetingAPI获取播放列表的,我觉得喜欢的可以换一下接口换成你的,接口网上很多,喜欢的自行部署吧!
这款美化版本的播放器还是不错的,音乐跟着歌词同步,并且当播放音乐的时候还左下角还有封面旋转的效果!
代码部署
将下面的代码丢到:子比主题–>>自定义底部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=tencent&type=playlist&id=3771408184');
- 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>
复制代码
|
|