领先的免费Web技术教程,涵盖HTML到ASP.NET

网站首页 > 知识剖析 正文

UI样式iPod classic的HTML本地音乐播放器框架

nixiaole 2025-06-28 15:45:09 知识剖析 1 ℃

PS:音量可以鼠标点击按住在音量图标边的轮盘上下拖拽滑动音量大小
中心按钮可以更改播放器为白色

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>iPod Classic 音乐播放器</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        :root {
            --primary-color: #333;
            --secondary-color: #555;
            --text-color: #fff;
            --light-text: #ccc;
            --highlight-color: #007AFF;
            --wheel-color: #1a1a1a;
            --screen-color: #000;
            --body-gradient-start: #2c3e50;
            --body-gradient-end: #1a1a1a;
            --ipod-gradient-start: #1a1a1a;
            --ipod-gradient-end: #000;
            --sidebar-gradient-start: rgba(0,0,0,0.9);
            --sidebar-gradient-end: rgba(30,30,30,0.9);
            --progress-bg: #555;
        }
        
        .light-theme {
            --primary-color: #f0f0f0;
            --secondary-color: #d0d0d0;
            --text-color: #222;
            --light-text: #666;
            --highlight-color: #0066cc;
            --wheel-color: #e0e0e0;
            --screen-color: #f5f5f5;
            --body-gradient-start: #e0e0e0;
            --body-gradient-end: #c0c0c0;
            --ipod-gradient-start: #f5f5f5;
            --ipod-gradient-end: #e0e0e0;
            --sidebar-gradient-start: rgba(245,245,245,0.95);
            --sidebar-gradient-end: rgba(230,230,230,0.95);
            --progress-bg: #d0d0d0;
        }
        
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            -webkit-tap-highlight-color: transparent;
            touch-action: manipulation;
        }
        
        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
            background: linear-gradient(135deg, rgba(44, 62, 80, 0.1), rgba(26, 26, 26, 0.1));
            height: 100vh;
            display: flex;
            justify-content: center;
            align-items: center;
            color: var(--text-color);
            overflow: hidden;
            transition: all 0.5s ease;
            padding: 16px;
            backdrop-filter: blur(3px);
            background-blend-mode: overlay;
        }
        
        .ipod-container {
            width: 100%;
            max-width: 384px;
            height: 660px;
            max-height: 90vh;
            background: linear-gradient(to bottom, var(--ipod-gradient-start), var(--ipod-gradient-end));
            border-radius: 48px;
            box-shadow: 0 24px 60px rgba(0,0,0,0.5),
                        inset 0 0 24px rgba(255,255,255,0.05);
            position: relative;
            overflow: hidden;
            transition: all 0.5s ease;
        }
        
        .screen {
            width: 90%;
            height: 40%;
            max-height: 288px;
            background: var(--screen-color);
            margin: 7% auto 5%;
            border-radius: 6px;
            padding: 16px;
            position: relative;
            overflow: hidden;
            box-shadow: inset 0 0 12px rgba(0,0,0,0.1);
            transition: background 0.5s ease;
        }
        
        .now-playing {
            display: flex;
            flex-direction: column;
            height: 100%;
            cursor: pointer;
            position: relative;
        }
        
        .album-art {
            width: 40%;
            max-width: 144px;
            aspect-ratio: 1/1;
            margin: 0 auto 12px;
            background: var(--wheel-color);
            border-radius: 6px;
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
            transition: background 0.5s ease;
            box-shadow: 0 6px 18px rgba(0,0,0,0.2);
        }
        
        .album-art img {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }
        
        .song-info {
            text-align: center;
            margin-bottom: 12px;
        }
        
        .song-title {
            font-size: clamp(18px, 4vw, 22px);
            font-weight: bold;
            margin-bottom: 6px;
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        
        .artist {
            font-size: clamp(14px, 3vw, 17px);
            color: var(--light-text);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
        }
        
        .progress-container {
            width: 100%;
            height: 5px;
            background: var(--progress-bg);
            border-radius: 3px;
            margin: 12px 0;
            cursor: pointer;
            position: relative;
        }
        
        .progress-bar {
            height: 100%;
            background: var(--highlight-color);
            border-radius: 3px;
            width: 0%;
            transition: width 0.1s linear;
        }
        
        .progress-handle {
            position: absolute;
            top: 50%;
            width: 12px;
            height: 12px;
            background: var(--text-color);
            border-radius: 50%;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: opacity 0.2s;
            box-shadow: 0 0 4px rgba(0,0,0,0.5);
        }
        
        .progress-container:hover .progress-handle {
            opacity: 1;
        }
        
        .time-display {
            display: flex;
            justify-content: space-between;
            font-size: clamp(12px, 2.5vw, 14px);
            color: var(--light-text);
            margin-bottom: 16px;
        }
        
        .click-wheel {
            width: 70%;
            max-width: 264px;
            aspect-ratio: 1/1;
            background: var(--wheel-color);
            border-radius: 50%;
            margin: 0 auto;
            position: relative;
            box-shadow: inset 0 0 24px rgba(0,0,0,0.1);
            display: flex;
            justify-content: center;
            align-items: center;
            user-select: none;
            transition: background 0.5s ease;
        }
        
        .wheel-center {
            width: 35%;
            max-width: 96px;
            aspect-ratio: 1/1;
            background: var(--screen-color);
            border-radius: 50%;
            display: flex;
            justify-content: center;
            align-items: center;
            color: var(--text-color);
            font-size: clamp(14px, 3vw, 17px);
            cursor: pointer;
            transition: all 0.2s;
            box-shadow: 0 0 12px rgba(0,0,0,0.1);
        }
        
        .wheel-center svg {
            width: 36px;
            height: 36px;
            fill: var(--text-color);
        }

        .wheel-center:hover svg {
            fill: var(--highlight-color);
        }

        .wheel-center:hover {
            background: var(--primary-color);
        }
        
        .wheel-btn {
            position: absolute;
            width: 15%;
            max-width: 48px;
            aspect-ratio: 1/1;
            background: none;
            border: none;
            color: var(--text-color);
            cursor: pointer;
            transition: all 0.2s;
            display: flex;
            justify-content: center;
            align-items: center;
        }
        
        .wheel-btn svg {
            width: 28.8px;
            height: 28.8px;
            fill: var(--text-color);
            transition: fill 0.2s;
        }
        
        .wheel-btn:hover svg {
            fill: var(--highlight-color);
        }
        
        .wheel-btn.active svg {
            fill: var(--highlight-color);
        }
        
        .menu-btn {
            top: 10%;
            left: 50%;
            transform: translateX(-50%);
        }
        
        .prev-btn {
            left: 10%;
            top: 50%;
            transform: translateY(-50%);
        }
        
        .next-btn {
            right: 10%;
            top: 50%;
            transform: translateY(-50%);
        }
        
        .play-btn {
            bottom: 10%;
            left: 50%;
            transform: translateX(-50%);
        }
        
        .sidebar {
            position: absolute;
            top: 0;
            left: -100%;
            width: 100%;
            height: 100%;
            background: linear-gradient(to right, var(--sidebar-gradient-start), var(--sidebar-gradient-end));
            border-radius: 48px 0 0 48px;
            padding: 36px 24px;
            transition: transform 0.3s ease-in-out;
            z-index: 15;
            box-shadow: 6px 0 18px rgba(0,0,0,0.2);
        }
        
        .sidebar.show {
            transform: translateX(100%);
        }
        
        .sidebar-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 24px;
            padding-bottom: 12px;
            border-bottom: 1.2px solid var(--secondary-color);
        }
        
        .sidebar-title {
            font-size: clamp(18px, 4vw, 22px);
            font-weight: bold;
        }
        
        .search-container {
            margin: 16px 0;
            position: relative;
        }
        
        #search-input {
            width: 100%;
            padding: 10px 15px;
            border-radius: 20px;
            border: none;
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-color);
            font-size: 14px;
            transition: background 0.3s;
        }
        
        #search-input:focus {
            outline: none;
            background: rgba(255, 255, 255, 0.2);
        }
        
        .light-theme #search-input {
            background: rgba(0, 0, 0, 0.1);
        }
        
        .light-theme #search-input:focus {
            background: rgba(0, 0, 0, 0.2);
        }
        
        .playlist {
            height: calc(100% - 160px);
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
        }
        
        .playlist::-webkit-scrollbar {
            width: 6px;
        }
        
        .playlist::-webkit-scrollbar-track {
            background: rgba(0,0,0,0.1);
        }
        
        .playlist::-webkit-scrollbar-thumb {
            background: var(--highlight-color);
            border-radius: 6px;
        }
        
        .playlist-item {
            padding: 12px;
            border-radius: 6px;
            margin-bottom: 6px;
            cursor: pointer;
            transition: background 0.2s;
            display: flex;
            align-items: center;
            gap: 12px;
        }
        
        .playlist-item:hover {
            background: rgba(0,0,0,0.05);
        }
        
        .playlist-item.active {
            background: rgba(0,122,255,0.2);
        }
        
        .playlist-song {
            font-size: clamp(14px, 3vw, 17px);
            font-weight: bold;
            margin-bottom: 3.6px;
        }
        
        .playlist-artist {
            font-size: clamp(12px, 2.5vw, 14px);
            color: var(--light-text);
        }
        
        .file-input-container {
            margin-top: 18px;
            position: relative;
        }
        
        .file-input-label {
            display: block;
            padding: 9.6px 14.4px;
            background: rgba(0,122,255,0.2);
            border-radius: 6px;
            text-align: center;
            font-size: clamp(14px, 3vw, 17px);
            cursor: pointer;
            transition: background 0.2s;
        }
        
        .file-input-label:hover {
            background: rgba(0,122,255,0.3);
        }
        
        #file-input {
            display: none;
        }
        
        .lyrics-view {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: var(--screen-color);
            padding: 18px;
            overflow: hidden;
            display: none;
            transition: background 0.5s ease;
            text-align: center;
            cursor: pointer;
            z-index: 10;
        }
        
        .lyrics-view.show {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        
        .lyrics-container {
            width: 100%;
            height: 100%;
            overflow-y: auto;
            padding: 20px 0;
            scrollbar-width: none;
            -ms-overflow-style: none;
            -webkit-overflow-scrolling: touch;
        }
        
        .lyrics-container::-webkit-scrollbar {
            display: none;
        }
        
        .lyrics-line {
            margin: 15px 0;
            font-size: clamp(16px, 3.5vw, 19px);
            color: var(--light-text);
            transition: all 0.3s;
            padding: 8px 0;
            min-height: 30px;
        }
        
        .lyrics-line.active {
            color: var(--highlight-color);
            font-size: clamp(18px, 4vw, 22px);
            font-weight: bold;
            transform: scale(1.05);
        }
        
        .overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0,0,0,0.3);
            display: none;
            z-index: 10;
            backdrop-filter: blur(3px);
        }
        
        .sidebar.show ~ .overlay {
            display: block;
        }
        
        .volume-display {
            position: absolute;
            bottom: 18px;
            left: 50%;
            transform: translateX(-50%);
            font-size: clamp(12px, 2.5vw, 14px);
            background: rgba(0,0,0,0.7);
            padding: 8px 16px;
            border-radius: 20px;
            display: none;
            z-index: 20;
            backdrop-filter: blur(5px);
            box-shadow: 0 4px 12px rgba(0,0,0,0.3);
        }
        
        .light-theme .volume-display {
            background: rgba(255,255,255,0.7);
        }
        
        .empty-state {
            text-align: center;
            padding: 40px 20px;
            color: var(--light-text);
        }
        
        .empty-state i {
            font-size: 48px;
            margin-bottom: 16px;
            color: var(--highlight-color);
        }
        
        .empty-state p {
            font-size: clamp(14px, 3vw, 16px);
            margin-top: 8px;
        }
        
        .song-icon {
            width: 36px;
            height: 36px;
            border-radius: 4px;
            background: var(--highlight-color);
            display: flex;
            align-items: center;
            justify-content: center;
        }
        
        .song-icon i {
            color: white;
            font-size: 16px;
        }
        
        .now-playing-placeholder {
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            height: 100%;
            text-align: center;
            color: var(--light-text);
            padding: 0 20px;
        }
        
        .now-playing-placeholder i {
            font-size: 48px;
            margin-bottom: 20px;
            color: var(--highlight-color);
        }
        
        .now-playing-placeholder p {
            font-size: clamp(14px, 3vw, 16px);
            line-height: 1.5;
        }
        
        /* 状态指示器 - 在now-playing内部 */
        .status-indicators {
            position: absolute;
            bottom: 10px;
            left: 0;
            width: 100%;
            display: flex;
            justify-content: center;
            gap: 15px;
            z-index: 5;
        }
        
        .status-indicator {
            display: flex;
            align-items: center;
            background: rgba(0,0,0,0.5);
            padding: 4px 10px;
            border-radius: 15px;
            font-size: 12px;
            gap: 5px;
            opacity: 0;
            transform: translateY(10px);
            transition: all 0.3s ease;
        }
        
        .status-indicator.show {
            opacity: 1;
            transform: translateY(0);
        }
        
        .light-theme .status-indicator {
            background: rgba(255,255,255,0.5);
        }
        
        .status-indicator i {
            font-size: 14px;
        }
        
        .status-indicator.active {
            background: rgba(0,122,255,0.5);
        }
        
        .status-indicator.active i {
            color: var(--highlight-color);
        }
        
        /* 优化单曲循环图标显示 */
        .single-loop-icon {
            transform: scale(0.85);
            transform-origin: center;
        }
        
        /* 旋转动画 */
        @keyframes rotateAlbum {
            from { transform: rotate(0deg); }
            to { transform: rotate(360deg); }
        }
        
        .playing .album-art img {
            animation: rotateAlbum 20s linear infinite;
        }
        
        /* 移动端优化 */
        @media (max-width: 480px) {
            .ipod-container {
                height: 580px;
                max-height: 85vh;
            }
            
            .screen {
                height: 35%;
                padding: 12px;
            }
            
            .click-wheel {
                width: 65%;
            }
            
            .sidebar {
                width: 85%;
            }
        }
        
        @media (max-width: 380px) {
            .ipod-container {
                height: 500px;
            }
            
            .screen {
                height: 32%;
                margin: 5% auto 4%;
            }
            
            .album-art {
                width: 35%;
            }
            
            .click-wheel {
                width: 60%;
            }
        }
        
        /* Safari 特定优化 */
        @media not all and (min-resolution:.001dpcm) { 
            @supports (-webkit-appearance:none) {
                .progress-container {
                    height: 6px;
                }
                
                .progress-handle {
                    width: 14px;
                    height: 14px;
                }
                
                .click-wheel {
                    -webkit-backface-visibility: hidden;
                    -webkit-transform: translate3d(0,0,0);
                }
            }
        }
    </style>
</head>
<body>
    <div class="ipod-container">
        <div class="volume-display" id="volume-display">音量: 100%</div>
        
        <div class="sidebar">
            <div class="sidebar-header">
                <div class="sidebar-title">播放列表</div>
            </div>
            <div class="search-container">
                <input type="text" id="search-input" placeholder="搜索歌曲...">
            </div>
            <div class="playlist" id="playlist">
                <div class="empty-state">
                    <i class="fas fa-music"></i>
                    <h3>播放列表为空</h3>
                    <p>添加音乐文件开始播放</p>
                </div>
            </div>
            <div class="file-input-container">
                <label for="file-input" class="file-input-label">添加音乐文件</label>
                <input type="file" id="file-input" accept="audio/*" multiple>
            </div>
        </div>
        
        <div class="overlay" id="overlay"></div>
        
        <div class="screen">
            <div class="now-playing" id="now-playing">
                <div class="status-indicators">
                    <div class="status-indicator" id="loop-indicator">
                        <i class="fas fa-repeat"></i>
                        <span>全部循环</span>
                    </div>
                    <div class="status-indicator" id="mute-indicator">
                        <i class="fas fa-volume-up"></i>
                        <span>音量开启</span>
                    </div>
                </div>
                
                <div class="now-playing-placeholder" id="now-playing-placeholder">
                    <i class="fas fa-music"></i>
                    <p>添加音乐文件开始播放</p>
                </div>
                <div class="album-art">
                    <img src="" alt="Album Art" id="album-art-img">
                </div>
                <div class="song-info">
                    <div class="song-title" id="song-title"></div>
                    <div class="artist" id="artist"></div>
                </div>
                <div class="progress-container" id="progress-container">
                    <div class="progress-bar" id="progress-bar"></div>
                    <div class="progress-handle" id="progress-handle"></div>
                </div>
                <div class="time-display">
                    <span id="current-time">0:00</span>
                    <span id="duration">0:00</span>
                </div>
            </div>
            
            <div class="lyrics-view" id="lyrics-view">
                <div class="lyrics-container" id="lyrics-container">
                    <div class="empty-state">
                        <i class="fas fa-file-alt"></i>
                        <h3>暂无歌词</h3>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="click-wheel">
            <button class="wheel-btn menu-btn" id="menu-btn">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
                    <path d="M0 96C0 78.3 14.3 64 32 64H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32C14.3 128 0 113.7 0 96zM0 256c0-17.7 14.3-32 32-32H416c17.7 0 32 14.3 32 32s-14.3 32-32 32H32c-17.7 0-32-14.3-32-32zM448 416c0 17.7-14.3 32-32 32H32c-17.7 0-32-14.3-32-32s14.3-32 32-32H416c17.7 0 32 14.3 32 32z"/>
                </svg>
            </button>
            <button class="wheel-btn prev-btn" id="wheel-prev-btn">
                <svg id="loop-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
                    <path d="M500.33 0h-47.41a12 12 0 0 0-12 12.57l4 82.76A247.42 247.42 0 0 0 256 8C119.34 8 7.9 119.53 8 256.19 8.1 393.07 119.1 504 256 504a247.1 247.1 0 0 0 166.18-63.91 12 12 0 0 0 .48-17.43l-34-34a12 12 0 0 0-16.38-.55A176 176 0 1 1 402.1 157.8l-101.53-4.87a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12h200.33a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12z"/>
                </svg>
            </button>
            <button class="wheel-btn next-btn" id="wheel-next-btn">
                <svg id="volume-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512">
                    <path d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zm233.32-51.08c-11.17-7.33-26.18-4.24-33.51 6.95-7.34 11.17-4.22 26.18 6.95 33.51 66.27 43.49 105.82 116.6 105.82 195.58 0 78.98-39.55 152.09-105.82 195.58-11.17 7.32-14.29 22.34-6.95 33.5 7.04 10.71 21.93 14.56 33.51 6.95C528.27 439.58 576 351.33 576 256S528.27 72.43 448.35 19.97zM480 256c0-63.53-32.06-121.94-85.77-156.24-11.19-7.14-26.03-3.82-33.12 7.46s-3.78 26.21 7.41 33.36C408.27 165.97 432 209.11 432 256c0 14.38-7.65 27.7-20.92 34.81-11.61 6.41-15.84 21-9.45 32.61 6.43 11.66 21.05 15.8 32.61 9.45 28.23-15.55 45.77-45 45.77-76.88s-17.54-61.32-45.78-76.86z"/>
                </svg>
            </button>
            <button class="wheel-btn play-btn" id="wheel-play-btn">
                <svg id="play-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">
                    <path d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"/>
                </svg>
            </button>
            <div class="wheel-center" id="wheel-center">
                <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512">
                    <path d="M318.7 268.7c-.2-36.7 16.4-64.4 50-84.8-18.8-26.9-47.2-41.7-84.7-44.6-35.5-2.8-74.3 20.7-88.5 20.7-15 0-49.4-19.7-76.4-19.7C63.3 141.2 4 184.8 4 273.5q0 39.3 14.4 81.2c12.8 36.7 59 126.7 107.2 125.2 25.2-.6 43-17.9 75.8-17.9 31.8 0 48.3 17.9 76.4 17.9 48.6-.7 90.4-82.5 102.6-119.3-65.2-30.7-61.7-90-61.7-91.9zm-56.6-164.2c27.3-32.4 24.8-61.9 24-72.5-24.1 1.4-52 16.4-67.9 34.9-17.5 19.8-27.8 44.3-25.6 71.9 26.1 2 49.9-11.4 69.5-34.3z"/>
                </svg>
            </div>
        </div>
        
        <audio id="audio-player"></audio>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', function() {
            // DOM元素
            const audioPlayer = document.getElementById('audio-player');
            const wheelPlayBtn = document.getElementById('wheel-play-btn');
            const wheelPrevBtn = document.getElementById('wheel-prev-btn');
            const wheelNextBtn = document.getElementById('wheel-next-btn');
            const menuBtn = document.getElementById('menu-btn');
            const wheelCenter = document.getElementById('wheel-center');
            const progressBar = document.getElementById('progress-bar');
            const progressContainer = document.getElementById('progress-container');
            const progressHandle = document.getElementById('progress-handle');
            const currentTimeEl = document.getElementById('current-time');
            const durationEl = document.getElementById('duration');
            const songTitle = document.getElementById('song-title');
            const artist = document.getElementById('artist');
            const sidebar = document.querySelector('.sidebar');
            const fileInput = document.getElementById('file-input');
            const playlist = document.getElementById('playlist');
            const lyricsView = document.getElementById('lyrics-view');
            const lyricsContainer = document.getElementById('lyrics-container');
            const nowPlaying = document.getElementById('now-playing');
            const nowPlayingPlaceholder = document.getElementById('now-playing-placeholder');
            const overlay = document.getElementById('overlay');
            const body = document.body;
            const playIcon = document.getElementById('play-icon');
            const volumeIcon = document.getElementById('volume-icon');
            const loopIcon = document.getElementById('loop-icon');
            const volumeDisplay = document.getElementById('volume-display');
            const albumArtImg = document.getElementById('album-art-img');
            const loopIndicator = document.getElementById('loop-indicator');
            const muteIndicator = document.getElementById('mute-indicator');
            const searchInput = document.getElementById('search-input');
            
            // 播放列表数据
            let songs = [];
            let currentSongIndex = -1;
            let isPlaying = false;
            let theme = 'dark';
            let loopMode = 'all'; // 'all' or 'single'
            let isMuted = false;
            let lastVolume = 1;
            let isDraggingProgress = false;
            
            // 初始化播放器
            function initPlayer() {
                renderPlaylist(songs);
                updateIndicators();
                
                // 事件监听
                wheelPlayBtn.addEventListener('click', togglePlay);
                wheelPrevBtn.addEventListener('click', function(e) {
                    toggleLoopMode(e);
                    showLoopIndicator();
                });
                wheelNextBtn.addEventListener('click', function(e) {
                    toggleMute(e);
                    showMuteIndicator();
                });
                menuBtn.addEventListener('click', toggleSidebar);
                wheelCenter.addEventListener('click', toggleTheme);
                progressContainer.addEventListener('click', setProgress);
                audioPlayer.addEventListener('timeupdate', updateProgress);
                audioPlayer.addEventListener('ended', nextSong);
                audioPlayer.addEventListener('loadedmetadata', updateDuration);
                fileInput.addEventListener('change', handleFileSelect);
                overlay.addEventListener('click', closeSidebar);
                nowPlaying.addEventListener('click', toggleLyricsView);
                lyricsView.addEventListener('click', toggleLyricsView);
                
                // 进度条拖动事件
                progressContainer.addEventListener('mousedown', startDragProgress);
                progressContainer.addEventListener('touchstart', startDragProgressTouch);
                document.addEventListener('mousemove', dragProgress);
                document.addEventListener('touchmove', dragProgressTouch);
                document.addEventListener('mouseup', endDragProgress);
                document.addEventListener('touchend', endDragProgress);
                
                // 搜索框功能
                searchInput.addEventListener('input', filterPlaylist);
                
                // 触摸轮盘事件
                setupWheelControls();
            }
            
            // 显示循环模式指示器
            function showLoopIndicator() {
                loopIndicator.classList.add('show');
                setTimeout(() => {
                    loopIndicator.classList.remove('show');
                }, 1500);
            }
            
            // 显示静音指示器
            function showMuteIndicator() {
                muteIndicator.classList.add('show');
                setTimeout(() => {
                    muteIndicator.classList.remove('show');
                }, 1500);
            }
            
            // 更新状态指示器
            function updateIndicators() {
                // 更新循环模式指示器
                if (loopMode === 'all') {
                    loopIndicator.innerHTML = '<i class="fas fa-repeat"></i><span>全部循环</span>';
                    loopIndicator.classList.remove('active');
                    loopIcon.innerHTML = '<path d="M500.33 0h-47.41a12 12 0 0 0-12 12.57l4 82.76A247.42 247.42 0 0 0 256 8C119.34 8 7.9 119.53 8 256.19 8.1 393.07 119.1 504 256 504a247.1 247.1 0 0 0 166.18-63.91 12 12 0 0 0 .48-17.43l-34-34a12 12 0 0 0-16.38-.55A176 176 0 1 1 402.1 157.8l-101.53-4.87a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12h200.33a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12z"/>';
                } else {
                    loopIndicator.innerHTML = '<i class="fas fa-repeat single-loop-icon"></i><span>单曲循环</span>';
                    loopIndicator.classList.add('active');
                    loopIcon.innerHTML = `
                        <svg t="1750649017434" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1504" width="520" height="520"><path d="M594.066286 937.472c33.645714 35.108571-21.504 88.868571-59.465143 55.003429l-115.785143-103.570286c-16.164571-14.482286-15.725714-42.715429-0.365714-57.344l114.102857-109.714286c36.644571-35.108571 91.721143 17.188571 60.928 53.394286 189.805714-21.942857 258.121143-230.253714 155.062857-379.904-59.684571-86.162286 78.043429-163.108571 136.996571-77.677714 179.712 260.169143 10.24 586.752-291.474285 619.812571z m-436.662857-231.350857c-179.638857-260.169143-10.313143-586.459429 291.254857-619.666286-33.572571-35.035429 21.577143-88.868571 59.465143-55.003428L623.908571 135.021714c16.091429 14.336 15.798857 42.569143 0.438858 57.344L510.171429 301.933714c-36.498286 35.108571-91.574857-17.188571-60.854858-53.394285-189.732571 21.942857-258.048 230.326857-154.843428 379.904 59.538286 86.016-78.116571 163.108571-136.996572 77.677714z" p-id="1505"></path></svg>
                    `;
                }
                
                // 更新静音指示器
                if (isMuted) {
                    muteIndicator.innerHTML = '<i class="fas fa-volume-mute"></i><span>静音中</span>';
                    muteIndicator.classList.add('active');
                    volumeIcon.innerHTML = '<path d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zm"/>';
                } else {
                    muteIndicator.innerHTML = '<i class="fas fa-volume-up"></i><span>音量开启</span>';
                    muteIndicator.classList.remove('active');
                    volumeIcon.innerHTML = '<path d="M215.03 71.05L126.06 160H24c-13.26 0-24 10.74-24 24v144c0 13.25 10.74 24 24 24h102.06l88.97 88.95c15.03 15.03 40.97 4.47 40.97-16.97V88.02c0-21.46-25.96-31.98-40.97-16.97zm233.32-51.08c-11.17-7.33-26.18-4.24-33.51 6.95-7.34 11.17-4.22 26.18 6.95 33.51 66.27 43.49 105.82 116.6 105.82 195.58 0 78.98-39.55 152.09-105.82 195.58-11.17 7.32-14.29 22.34-6.95 33.5 7.04 10.71 21.93 14.56 33.51 6.95C528.27 439.58 576 351.33 576 256S528.27 72.43 448.35 19.97zM480 256c0-63.53-32.06-121.94-85.77-156.24-11.19-7.14-26.03-3.82-33.12 7.46s-3.78 26.21 7.41 33.36C408.27 165.97 432 209.11 432 256c0 14.38-7.65 27.7-20.92 34.81-11.61 6.41-15.84 21-9.45 32.61 6.43 11.66 21.05 15.8 32.61 9.45 28.23-15.55 45.77-45 45.77-76.88s-17.54-61.32-45.78-76.86z"/>';
                }
            }
            
            // 更新播放器信息
            function updatePlayerInfo() {
                if (currentSongIndex === -1 || songs.length === 0) {
                    // 没有歌曲
                    nowPlayingPlaceholder.style.display = 'flex';
                    songTitle.textContent = '';
                    artist.textContent = '';
                    albumArtImg.src = '';
                    albumArtImg.style.display = 'none';
                    progressContainer.style.display = 'none';
                    return;
                }
                
                const song = songs[currentSongIndex];
                songTitle.textContent = song.title;
                artist.textContent = song.artist;
                
                // 显示专辑封面
                albumArtImg.src = song.art || 'https://images.unsplash.com/photo-1470225620780-dba8ba36b745?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80';
                albumArtImg.style.display = 'block';
                nowPlayingPlaceholder.style.display = 'none';
                progressContainer.style.display = 'block';
                
                // 更新播放列表高亮
                const playlistItems = playlist.querySelectorAll('.playlist-item');
                playlistItems.forEach((item, index) => {
                    if (index === currentSongIndex) {
                        item.classList.add('active');
                    } else {
                        item.classList.remove('active');
                    }
                });
                
                // 更新歌词
                updateLyrics();
            }
            
            // 播放/暂停切换
            function togglePlay() {
                if (songs.length === 0 || currentSongIndex === -1) return;
                
                if (isPlaying) {
                    pauseSong();
                } else {
                    playSong();
                }
            }
            
            // 播放歌曲
            function playSong() {
                if (songs.length === 0 || currentSongIndex === -1) return;
                
                audioPlayer.src = songs[currentSongIndex].src;
                audioPlayer.play().catch(error => {
                    console.error('播放错误:', error);
                    alert('无法播放音频,请确保文件格式受支持');
                });
                
                isPlaying = true;
                updatePlayIcon();
                document.querySelector('.ipod-container').classList.add('playing');
            }
            
            // 暂停歌曲
            function pauseSong() {
                audioPlayer.pause();
                isPlaying = false;
                updatePlayIcon();
                document.querySelector('.ipod-container').classList.remove('playing');
            }
            
            // 更新播放图标
            function updatePlayIcon() {
                if (isPlaying) {
                    playIcon.innerHTML = '<path d="M144 479H48c-26.5 0-48-21.5-48-48V79c0-26.5 21.5-48 48-48h96c26.5 0 48 21.5 48 48v352c0 26.5-21.5 48-48 48zm304-48V79c0-26.5-21.5-48-48-48h-96c-26.5 0-48 21.5-48 48v352c0 26.5 21.5 48 48 48h96c26.5 0 48-21.5 48-48z"/>';
                } else {
                    playIcon.innerHTML = '<path d="M424.4 214.7L72.4 6.6C43.8-10.3 0 6.1 0 47.9V464c0 37.5 40.7 60.1 72.4 41.3l352-208c31.4-18.5 31.5-64.1 0-82.6z"/>';
                }
            }
            
            // 切换循环模式
            function toggleLoopMode(e) {
                e.stopPropagation(); // 防止事件冒泡
                
                if (loopMode === 'all') {
                    loopMode = 'single';
                } else {
                    loopMode = 'all';
                }
                
                updateIndicators();
            }
            
            // 切换静音
            function toggleMute(e) {
                e.stopPropagation(); // 防止事件冒泡
                
                if (isMuted) {
                    // 取消静音
                    audioPlayer.muted = false;
                    audioPlayer.volume = lastVolume;
                    isMuted = false;
                } else {
                    // 静音
                    lastVolume = audioPlayer.volume;
                    audioPlayer.muted = true;
                    isMuted = true;
                }
                
                updateIndicators();
            }
            
            // 上一首
            function prevSong() {
                if (songs.length === 0 || currentSongIndex === -1) return;
                
                if (loopMode === 'single') {
                    audioPlayer.currentTime = 0;
                    playSong();
                    return;
                }
                
                currentSongIndex--;
                if (currentSongIndex < 0) {
                    currentSongIndex = songs.length - 1;
                }
                
                updatePlayerInfo();
                playSong();
            }
            
            // 下一首
            function nextSong() {
                if (songs.length === 0 || currentSongIndex === -1) return;
                
                if (loopMode === 'single') {
                    audioPlayer.currentTime = 0;
                    playSong();
                    return;
                }
                
                currentSongIndex++;
                if (currentSongIndex >= songs.length) {
                    currentSongIndex = 0;
                }
                
                updatePlayerInfo();
                playSong();
            }
            
            // 更新进度条
            function updateProgress() {
                const { currentTime, duration } = audioPlayer;
                const progressPercent = (currentTime / duration) * 100;
                progressBar.style.width = `${progressPercent}%`;
                progressHandle.style.left = `${progressPercent}%`;
                
                // 更新时间显示
                currentTimeEl.textContent = formatTime(currentTime);
                
                // 更新歌词高亮
                updateLyricsHighlight(currentTime);
            }
            
            // 设置进度
            function setProgress(e) {
                const width = this.clientWidth;
                const clickX = e.offsetX;
                const duration = audioPlayer.duration;
                audioPlayer.currentTime = (clickX / width) * duration;
            }
            
            // 开始拖动进度条 (鼠标)
            function startDragProgress(e) {
                isDraggingProgress = true;
                const width = progressContainer.clientWidth;
                const clickX = e.offsetX;
                const duration = audioPlayer.duration;
                audioPlayer.currentTime = (clickX / width) * duration;
                progressHandle.style.opacity = 1;
            }
            
            // 开始拖动进度条 (触摸)
            function startDragProgressTouch(e) {
                isDraggingProgress = true;
                const rect = progressContainer.getBoundingClientRect();
                const touch = e.touches[0];
                const clickX = touch.clientX - rect.left;
                const width = rect.width;
                const duration = audioPlayer.duration;
                audioPlayer.currentTime = (clickX / width) * duration;
                progressHandle.style.opacity = 1;
            }
            
            // 拖动进度条 (鼠标)
            function dragProgress(e) {
                if (!isDraggingProgress) return;
                
                const rect = progressContainer.getBoundingClientRect();
                let clickX = e.clientX - rect.left;
                clickX = Math.max(0, Math.min(rect.width, clickX));
                
                const progressPercent = (clickX / rect.width) * 100;
                progressBar.style.width = `${progressPercent}%`;
                progressHandle.style.left = `${progressPercent}%`;
                
                const duration = audioPlayer.duration;
                audioPlayer.currentTime = (clickX / rect.width) * duration;
            }
            
            // 拖动进度条 (触摸)
            function dragProgressTouch(e) {
                if (!isDraggingProgress) return;
                e.preventDefault();
                
                const rect = progressContainer.getBoundingClientRect();
                const touch = e.touches[0];
                let clickX = touch.clientX - rect.left;
                clickX = Math.max(0, Math.min(rect.width, clickX));
                
                const progressPercent = (clickX / rect.width) * 100;
                progressBar.style.width = `${progressPercent}%`;
                progressHandle.style.left = `${progressPercent}%`;
                
                const duration = audioPlayer.duration;
                audioPlayer.currentTime = (clickX / rect.width) * duration;
            }
            
            // 结束拖动
            function endDragProgress() {
                isDraggingProgress = false;
                progressHandle.style.opacity = '';
            }
            
            // 更新总时长
            function updateDuration() {
                durationEl.textContent = formatTime(audioPlayer.duration);
            }
            
            // 格式化时间
            function formatTime(seconds) {
                if (isNaN(seconds)) return "0:00";
                
                const mins = Math.floor(seconds / 60);
                const secs = Math.floor(seconds % 60);
                return `${mins}:${secs < 10 ? '0' : ''}${secs}`;
            }
            
            // 切换侧边栏
            function toggleSidebar() {
                sidebar.classList.add('show');
                overlay.style.display = 'block';
            }
            
            // 关闭侧边栏
            function closeSidebar() {
                sidebar.classList.remove('show');
                overlay.style.display = 'none';
            }
            
            // 设置覆盖层点击事件
            overlay.addEventListener('click', function(e) {
                if (e.target === overlay) {
                    closeSidebar();
                }
            });
            
            // 处理文件选择
            function handleFileSelect(e) {
                const files = e.target.files;
                
                // 移除空状态
                const emptyState = playlist.querySelector('.empty-state');
                if (emptyState) {
                    emptyState.remove();
                }
                
                for (let i = 0; i < files.length; i++) {
                    const file = files[i];
                    if (!file.type.match('audio.*')) continue;
                    
                    const song = {
                        title: file.name.replace(/\.[^/.]+$/, ""),
                        artist: "未知艺术家",
                        src: URL.createObjectURL(file),
                        art: "https://images.unsplash.com/photo-1470225620780-dba8ba36b745?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80",
                        lyrics: [
                            {time: 0, text: file.name.replace(/\.[^/.]+$/, "")},
                            {time: 5, text: "暂无歌词"}
                        ]
                    };
                    
                    songs.push(song);
                    
                    // 如果是第一首歌曲,设置为当前播放
                    if (songs.length === 1) {
                        currentSongIndex = 0;
                        updatePlayerInfo();
                    }
                    
                    // 添加到播放列表
                    const playlistItem = document.createElement('div');
                    playlistItem.className = 'playlist-item';
                    playlistItem.innerHTML = `
                        <div class="song-icon">
                            <i class="fas fa-music"></i>
                        </div>
                        <div>
                            <div class="playlist-song">${song.title}</div>
                            <div class="playlist-artist">${song.artist}</div>
                        </div>
                    `;
                    
                    playlistItem.addEventListener('click', () => {
                        currentSongIndex = songs.indexOf(song);
                        updatePlayerInfo();
                        playSong();
                        closeSidebar();
                    });
                    
                    playlist.appendChild(playlistItem);
                }
                
                // 重置文件输入,允许重复选择相同文件
                fileInput.value = '';
                renderPlaylist(songs);
            }
            
            // 切换歌词视图
            function toggleLyricsView() {
                if (songs.length === 0 || currentSongIndex === -1) return;
                
                lyricsView.classList.toggle('show');
                nowPlaying.style.display = lyricsView.classList.contains('show') ? 'none' : 'flex';
                updateLyricsHighlight(audioPlayer.currentTime);
            }
            
            // 更新歌词
            function updateLyrics() {
                const lyricsContainer = document.getElementById('lyrics-container');
                const song = songs[currentSongIndex];
                
                if (song.lyrics && song.lyrics.length > 0) {
                    lyricsContainer.innerHTML = '';
                    song.lyrics.forEach(line => {
                        const lyricLine = document.createElement('div');
                        lyricLine.className = 'lyrics-line';
                        lyricLine.textContent = line.text;
                        lyricLine.dataset.time = line.time;
                        lyricsContainer.appendChild(lyricLine);
                    });
                } else {
                    lyricsContainer.innerHTML = '<div class="empty-state"><i class="fas fa-file-alt"></i><h3>暂无歌词</h3></div>';
                }
            }
            
            // 更新歌词高亮
            function updateLyricsHighlight(currentTime) {
                const lyricsLines = document.querySelectorAll('.lyrics-line');
                const song = songs[currentSongIndex];
                
                if (!song || !song.lyrics || lyricsLines.length === 0) return;
                
                let activeLine = null;
                
                for (let i = 0; i < song.lyrics.length; i++) {
                    if (currentTime >= song.lyrics[i].time) {
                        activeLine = i;
                    } else {
                        break;
                    }
                }
                
                lyricsLines.forEach((line, index) => {
                    if (index === activeLine) {
                        line.classList.add('active');
                        // 滚动到可视区域
                        if (lyricsView.classList.contains('show')) {
                            line.scrollIntoView({ behavior: 'smooth', block: 'center' });
                        }
                    } else {
                        line.classList.remove('active');
                    }
                });
            }
            
            // 切换主题
            function toggleTheme() {
                if (theme === 'dark') {
                    body.classList.add('light-theme');
                    theme = 'light';
                } else {
                    body.classList.remove('light-theme');
                    theme = 'dark';
                }
            }
            
            // 设置轮盘控制
            function setupWheelControls() {
                const wheel = document.querySelector('.click-wheel');
                let startAngle = 0;
                let currentAngle = 0;
                let rotation = 0;
                let isRotating = false;
                let volumeTimeout;
                
                wheel.addEventListener('mousedown', startRotation);
                wheel.addEventListener('touchstart', startRotation);
                document.addEventListener('mousemove', rotate);
                document.addEventListener('touchmove', rotate);
                document.addEventListener('mouseup', endRotation);
                document.addEventListener('touchend', endRotation);
                
                function startRotation(e) {
                    e.preventDefault();
                    const rect = wheel.getBoundingClientRect();
                    const centerX = rect.left + rect.width / 2;
                    const centerY = rect.top + rect.height / 2;
                    
                    let clientX, clientY;
                    
                    if (e.type === 'touchstart') {
                        clientX = e.touches[0].clientX;
                        clientY = e.touches[0].clientY;
                    } else {
                        clientX = e.clientX;
                        clientY = e.clientY;
                    }
                    
                    startAngle = Math.atan2(clientY - centerY, clientX - centerX) * 180 / Math.PI;
                    isRotating = true;
                }
                
                function rotate(e) {
                    if (!isRotating) return;
                    e.preventDefault();
                    
                    const rect = wheel.getBoundingClientRect();
                    const centerX = rect.left + rect.width / 2;
                    const centerY = rect.top + rect.height / 2;
                    
                    let clientX, clientY;
                    
                    if (e.type === 'touchmove') {
                        clientX = e.touches[0].clientX;
                        clientY = e.touches[0].clientY;
                    } else {
                        clientX = e.clientX;
                        clientY = e.clientY;
                    }
                    
                    currentAngle = Math.atan2(clientY - centerY, clientX - centerX) * 180 / Math.PI;
                    rotation = currentAngle - startAngle;
                    
                    // 根据旋转角度调整音量
                    if (Math.abs(rotation) > 5) {
                        const volumeChange = rotation > 0 ? 0.05 : -0.05;
                        let newVolume = audioPlayer.volume + volumeChange;
                        newVolume = Math.max(0, Math.min(1, newVolume));
                        audioPlayer.volume = newVolume;
                        
                        // 更新音量显示
                        volumeDisplay.textContent = `音量: ${Math.round(newVolume * 100)}%`;
                        volumeDisplay.style.display = 'block';
                        
                        // 清除之前的超时
                        if (volumeTimeout) clearTimeout(volumeTimeout);
                        
                        // 设置超时隐藏音量显示
                        volumeTimeout = setTimeout(() => {
                            volumeDisplay.style.display = 'none';
                        }, 2000);
                        
                        startAngle = currentAngle;
                    }
                }
                
                function endRotation() {
                    isRotating = false;
                }
            }
            
            // 渲染播放列表
            function renderPlaylist(list) {
                const playlist = document.getElementById('playlist');
                
                // 清空播放列表
                playlist.innerHTML = '';
                
                // 如果列表为空,显示空状态
                if (list.length === 0) {
                    playlist.innerHTML = `
                        <div class="empty-state">
                            <i class="fas fa-music"></i>
                            <h3>播放列表为空</h3>
                            <p>添加音乐文件开始播放</p>
                        </div>
                    `;
                    return;
                }
                
                // 添加歌曲到播放列表
                list.forEach(song => {
                    const playlistItem = document.createElement('div');
                    playlistItem.className = 'playlist-item';
                    playlistItem.innerHTML = `
                        <div class="song-icon">
                            <i class="fas fa-music"></i>
                        </div>
                        <div>
                            <div class="playlist-song">${song.title}</div>
                            <div class="playlist-artist">${song.artist}</div>
                        </div>
                    `;
                    
                    playlistItem.addEventListener('click', () => {
                        currentSongIndex = songs.indexOf(song);
                        updatePlayerInfo();
                        playSong();
                        closeSidebar();
                    });
                    
                    playlist.appendChild(playlistItem);
                });
            }
            
            // 搜索
            function filterPlaylist() {
                const searchTerm = searchInput.value.toLowerCase().trim();
                
                if (!searchTerm) {
                    renderPlaylist(songs);
                    return;
                }
                
                // 过滤匹配的歌曲
                const filteredSongs = songs.filter(song => 
                    song.title.toLowerCase().includes(searchTerm) || 
                    song.artist.toLowerCase().includes(searchTerm)
                );
                
                // 渲染过滤后的播放列表
                renderPlaylist(filteredSongs);
            }
            
            // 初始化播放器
            initPlayer();
        });
    </script>
</body>
</html>
最近发表
标签列表