会员仅9.9元起,全站资源无限制ALL免费下载!

子比主题 – 左下角音乐播放器美化版

文章最后更新时间:2025-08-31 20:37:13

逛论坛的时候发现一个美化播放器,这个播放器还是不错的,用了一下,是从从MetingAPI获取播放列表的,我觉得喜欢的可以换一下接口换成你的,接口网上很多,喜欢的自行部署吧!文章源自奇客源码-https://www.qkget.cn/6012.html

图片[1]-子比主题 – 左下角音乐播放器美化版-奇客源码文章源自奇客源码-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

© 版权声明
THE END
点赞10赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容