【免费】本站同款音乐播放器

mgrdmx · · · 更新于 2026年2月15日 · 60,758 字 · 约 152 分钟
33 1
AI摘要介绍

本文介绍一款免费开源的音乐播放器,它基于MetingApi驱动,可适配多种网站。该播放器解决了收费、歌曲添加繁琐及部分音乐无法播放等问题,并支持替换API地址以保持稳定运行。


本站同款音乐播放器免费开源

还在因网站播放器是收费的而烦恼?
还在因播放器歌曲太难添加而耗时间?
还在因某些音乐是收费的导致不能播放而痛苦?
现在我将开源本站的音乐播放器,理论上是适用所有网站的,可以添加到自己的其他网站试试
本播放器基于MetingApi作为核心驱动,所以即使这个MetingApi的地址失效了,还可以换其他的(搜索引擎一搜一大堆),例如如果https://music.3e0.cn/ 这个api失效了,只需要搜索https://music.3e0.cn/ 并替换成其他api例如https://xxx.com
歌单ID也可以换
本播放器修复了大量BUG,已经很稳定了
遇到其他网站和本网站(blog.3e0.cn)一模一的播放器都是出自本网站所开源的
在下面代码中播放器的歌单是网易云热歌榜
以下是代码
纯文本
</div><div><br></div><div><style></div><div>.meting-player-container * {</div><div>    margin: 0;</div><div>    padding: 0;</div><div>    box-sizing: border-box;</div><div>    font-family: 'Microsoft YaHei', sans-serif;</div><div>}</div><div><br></div><div>.meting-player-container {</div><div>    position: fixed;</div><div>    left: 20px;</div><div>    bottom: 70px;</div><div>    z-index: 1000;</div><div>    width: 360px;</div><div>    transition: all 0.3s ease;</div><div>}</div><div><br></div><div>.meting-player-container.minimized {</div><div>    width: 50px;</div><div>    height: 50px;</div><div>}</div><div><br></div><div>.meting-player-main {</div><div>    background: rgba(60, 66, 64, 0.9);</div><div>    border-radius: 12px;</div><div>    overflow: hidden;</div><div>    box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);</div><div>    color: white;</div><div>    display: flex;</div><div>    flex-direction: column;</div><div>    transition: all 0.3s ease;</div><div>}</div><div><br></div><div>.minimized .meting-player-main {</div><div>    height: 50px;</div><div>    width: 50px;</div><div>    border-radius: 50%;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: center;</div><div>}</div><div><br></div><div>.meting-album-cover {</div><div>    display: none;</div><div>    width: 40px;</div><div>    height: 40px;</div><div>    border-radius: 50%;</div><div>    object-fit: cover;</div><div>    animation: meting-rotate 10s linear infinite;</div><div>    animation-play-state: paused;</div><div>}</div><div><br></div><div>.minimized .meting-album-cover {</div><div>    display: block;</div><div>}</div><div><br></div><div>.playing .meting-album-cover {</div><div>    animation-play-state: running;</div><div>}</div><div><br></div><div>@keyframes meting-rotate {</div><div>    100% {</div><div>        transform: rotate(360deg);</div><div>    }</div><div>}</div><div><br></div><div>.meting-player-header {</div><div>    display: flex;</div><div>    align-items: center;</div><div>    padding: 12px 15px;</div><div>    border-bottom: 1px solid rgba(255, 255, 255, 0.1);</div><div>}</div><div><br></div><div>.minimized .meting-player-header {</div><div>    display: none;</div><div>}</div><div><br></div><div>.meting-song-info {</div><div>    flex: 1;</div><div>    overflow: hidden;</div><div>}</div><div><br></div><div>.meting-song-title {</div><div>    font-size: 14px;</div><div>    white-space: nowrap;</div><div>    overflow: hidden;</div><div>    text-overflow: ellipsis;</div><div>}</div><div><br></div><div>.meting-song-artist {</div><div>    font-size: 12px;</div><div>    opacity: 0.8;</div><div>    white-space: nowrap;</div><div>    overflow: hidden;</div><div>    text-overflow: ellipsis;</div><div>}</div><div><br></div><div>.meting-player-controls {</div><div>    display: flex;</div><div>    flex-direction: column;</div><div>    padding: 15px;</div><div>}</div><div><br></div><div>.minimized .meting-player-controls {</div><div>    display: none;</div><div>}</div><div><br></div><div>.meting-progress-top {</div><div>    display: flex;</div><div>    align-items: center;</div><div>    margin-bottom: 15px;</div><div>    width: 100%;</div><div>}</div><div><br></div><div>.meting-progress-container {</div><div>    flex: 1;</div><div>    height: 12px;</div><div>    background: rgba(255, 255, 255, 0.3);</div><div>    border-radius: 6px;</div><div>    margin-right: 10px;</div><div>    cursor: pointer;</div><div>    position: relative;</div><div>}</div><div><br></div><div>.meting-progress-bar {</div><div>    height: 100%;</div><div>    background: #1db954;</div><div>    border-radius: 6px;</div><div>    width: 0%;</div><div>}</div><div><br></div><div>.meting-time-display {</div><div>    font-size: 12px;</div><div>    opacity: 0.8;</div><div>    min-width: 80px;</div><div>    text-align: center;</div><div>}</div><div><br></div><div>.meting-controls-bottom {</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: space-between;</div><div>    width: 100%;</div><div>}</div><div><br></div><div>.meting-control-buttons {</div><div>    display: flex;</div><div>    align-items: center;</div><div>}</div><div><br></div><div>.meting-control-btn,</div><div>.meting-volume-btn,</div><div>.meting-toggle-player,</div><div>.meting-lyrics-btn,</div><div>.meting-playlist-btn,</div><div>.meting-mode-btn {</div><div>    -webkit-tap-highlight-color: transparent;</div><div>    outline: none;</div><div>}</div><div><br></div><div>.meting-control-btn {</div><div>    background: none;</div><div>    border: none;</div><div>    color: white;</div><div>    font-size: 20px;</div><div>    cursor: pointer;</div><div>    margin: 0 5px;</div><div>    transition: all 0.2s;</div><div>    width: 32px;</div><div>    height: 32px;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: center;</div><div>}</div><div><br></div><div>.meting-control-btn:hover {</div><div>    color: #1db954;</div><div>}</div><div><br></div><div>.meting-play-pause {</div><div>    font-size: 32px;</div><div>    width: 40px;</div><div>    height: 40px;</div><div>}</div><div><br></div><div>.meting-volume-container {</div><div>    display: flex;</div><div>    align-items: center;</div><div>}</div><div><br></div><div>.meting-volume-btn {</div><div>    background: none;</div><div>    border: none;</div><div>    color: white;</div><div>    font-size: 18px;</div><div>    cursor: pointer;</div><div>    width: 24px;</div><div>    height: 24px;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: center;</div><div>}</div><div><br></div><div>.meting-volume-slider {</div><div>    width: 80px;</div><div>    margin-left: 5px;</div><div>    -webkit-appearance: none;</div><div>    height: 4px;</div><div>    background: rgba(255, 255, 255, 0.3);</div><div>    border-radius: 2px;</div><div>    outline: none;</div><div>    -webkit-tap-highlight-color: transparent;</div><div>}</div><div><br></div><div>.meting-volume-slider::-webkit-slider-thumb {</div><div>    -webkit-appearance: none;</div><div>    width: 12px;</div><div>    height: 12px;</div><div>    border-radius: 50%;</div><div>    background: #fff;</div><div>    cursor: pointer;</div><div>}</div><div><br></div><div>.meting-toggle-player {</div><div>    position: absolute;</div><div>    top: -10px;</div><div>    right: -10px;</div><div>    width: 24px;</div><div>    height: 24px;</div><div>    border-radius: 50%;</div><div>    background: #1db954;</div><div>    color: white;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: center;</div><div>    cursor: pointer;</div><div>    box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);</div><div>    border: none;</div><div>    font-size: 14px;</div><div>    transition: all 0.2s;</div><div>}</div><div><br></div><div>.meting-toggle-player:hover {</div><div>    transform: scale(1.1);</div><div>}</div><div><br></div><div>.meting-lyrics-container {</div><div>    position: fixed;</div><div>    bottom: 0;</div><div>    left: 0;</div><div>    right: 0;</div><div>    text-align: center;</div><div>    padding: 10px;</div><div>    background: rgba(0, 0, 0, 0.5);</div><div>    color: white;</div><div>    font-size: 16px;</div><div>    z-index: 900;</div><div>    transition: all 0.3s;</div><div>    line-height: 1.5;</div><div>}</div><div><br></div><div>.meting-lyrics-line {</div><div>    margin: 5px 0;</div><div>    opacity: 0.5;</div><div>    transition: all 0.3s;</div><div>}</div><div><br></div><div>.meting-lyrics-line.active {</div><div>    opacity: 1;</div><div>    color: #1db954;</div><div>    font-weight: bold;</div><div>    transform: scale(1.05);</div><div>}</div><div><br></div><div>.meting-playlist-btn {</div><div>    background: none;</div><div>    border: none;</div><div>    color: white;</div><div>    font-size: 20px;</div><div>    cursor: pointer;</div><div>    margin-left: 10px;</div><div>    width: 24px;</div><div>    height: 24px;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: center;</div><div>}</div><div><br></div><div>.meting-lyrics-btn {</div><div>    background: none;</div><div>    border: none;</div><div>    color: white;</div><div>    font-size: 16px;</div><div>    cursor: pointer;</div><div>    margin-left: 10px;</div><div>    width: 24px;</div><div>    height: 24px;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: center;</div><div>    font-weight: bold;</div><div>}</div><div><br></div><div>.meting-lyrics-btn.active {</div><div>    color: #1db954;</div><div>}</div><div><br></div><div>/* 重新设计播放列表样式 - 更美观的电脑端播放列表 */</div><div>.meting-playlist-container {</div><div>    position: absolute;</div><div>    bottom: calc(100% + 10px);</div><div>    left: 0;</div><div>    right: 0;</div><div>    background: rgba(60, 66, 64, 0.9);</div><div>    backdrop-filter: blur(10px);</div><div>    border-radius: 12px;</div><div>    max-height: 400px;</div><div>    overflow-y: auto;</div><div>    display: none;</div><div>    padding: 15px;</div><div>    box-shadow: 0 -5px 25px rgba(0, 0, 0, 0.4);</div><div>    border: 1px solid rgba(255, 255, 255, 0.1);</div><div>    scrollbar-width: thin;</div><div>    scrollbar-color: #1db954 rgba(255, 255, 255, 0.1);</div><div>}</div><div><br></div><div>.meting-playlist-container::-webkit-scrollbar {</div><div>    width: 6px;</div><div>}</div><div><br></div><div>.meting-playlist-container::-webkit-scrollbar-track {</div><div>    background: rgba(255, 255, 255, 0.05);</div><div>    border-radius: 3px;</div><div>}</div><div><br></div><div>.meting-playlist-container::-webkit-scrollbar-thumb {</div><div>    background-color: #1db954;</div><div>    border-radius: 3px;</div><div>}</div><div>/* 本播放器来源blog.3e0.cn 使用请保留本标识 */</div><div>.meting-playlist-container.show {</div><div>    display: block;</div><div>}</div><div><br></div><div>.meting-playlist-header {</div><div>    display: flex;</div><div>    justify-content: space-between;</div><div>    align-items: center;</div><div>    margin-bottom: 15px;</div><div>    padding-bottom: 10px;</div><div>    border-bottom: 1px solid rgba(255, 255, 255, 0.1);</div><div>}</div><div><br></div><div>.meting-playlist-title {</div><div>    font-size: 16px;</div><div>    font-weight: bold;</div><div>    color: #fff;</div><div>}</div><div><br></div><div>.meting-playlist-count {</div><div>    font-size: 13px;</div><div>    opacity: 0.7;</div><div>}</div><div><br></div><div>.meting-playlist-items {</div><div>    display: flex;</div><div>    flex-direction: column;</div><div>    gap: 8px;</div><div>}</div><div><br></div><div>.meting-playlist-item {</div><div>    padding: 12px 15px;</div><div>    border-radius: 8px;</div><div>    cursor: pointer;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    transition: all 0.2s ease;</div><div>    background: rgba(255, 255, 255, 0.03);</div><div>    -webkit-tap-highlight-color: transparent;</div><div>    outline: none;</div><div>}</div><div><br></div><div>.meting-playlist-item:hover {</div><div>    background: rgba(29, 185, 84, 0.15);</div><div>    transform: translateY(-2px);</div><div>}</div><div><br></div><div>.meting-playlist-item.playing {</div><div>    background: rgba(29, 185, 84, 0.2);</div><div>    box-shadow: 0 4px 12px rgba(29, 185, 84, 0.2);</div><div>}</div><div><br></div><div>.meting-playlist-item.playing .meting-playlist-item-index {</div><div>    color: #1db954;</div><div>    font-weight: bold;</div><div>}</div><div><br></div><div>.meting-playlist-item.playing .meting-playlist-item-title {</div><div>    color: #1db954;</div><div>}</div><div><br></div><div>.meting-playlist-item-index {</div><div>    margin-right: 15px;</div><div>    font-size: 14px;</div><div>    opacity: 0.8;</div><div>    min-width: 24px;</div><div>    text-align: center;</div><div>    transition: all 0.2s ease;</div><div>}</div><div><br></div><div>.meting-playlist-item-info {</div><div>    flex: 1;</div><div>    overflow: hidden;</div><div>    min-width: 0;</div><div>}</div><div><br></div><div>.meting-playlist-item-title {</div><div>    font-size: 14px;</div><div>    font-weight: 500;</div><div>    white-space: nowrap;</div><div>    overflow: hidden;</div><div>    text-overflow: ellipsis;</div><div>    margin-bottom: 3px;</div><div>    transition: all 0.2s ease;</div><div>}</div><div><br></div><div>.meting-playlist-item-artist {</div><div>    font-size: 12px;</div><div>    opacity: 0.7;</div><div>    white-space: nowrap;</div><div>    overflow: hidden;</div><div>    text-overflow: ellipsis;</div><div>}</div><div><br></div><div>.meting-playlist-item-duration {</div><div>    font-size: 12px;</div><div>    opacity: 0.6;</div><div>    margin-left: 10px;</div><div>    min-width: 40px;</div><div>    text-align: right;</div><div>}</div><div><br></div><div>.meting-mode-btn {</div><div>    background: none;</div><div>    border: none;</div><div>    color: white;</div><div>    font-size: 16px;</div><div>    cursor: pointer;</div><div>    margin-left: 5px;</div><div>    width: 24px;</div><div>    height: 24px;</div><div>    display: flex;</div><div>    align-items: center;</div><div>    justify-content: center;</div><div>}</div><div><br></div><div>@media screen and (max-width: 768px) {</div><div>    .meting-player-container {</div><div>        left: 10px;</div><div>        right: auto;</div><div>        bottom: 20px;</div><div>        width: auto;</div><div>        max-width: 320px;</div><div>        margin: 0;</div><div>    }</div><div>    </div><div>    .meting-player-main {</div><div>        border-radius: 10px;</div><div>    }</div><div>    </div><div>    .meting-player-header {</div><div>        padding: 10px;</div><div>    }</div><div>    </div><div>    .meting-song-title {</div><div>        font-size: 13px;</div><div>    }</div><div>    </div><div>    .meting-song-artist {</div><div>        font-size: 11px;</div><div>    }</div><div>    </div><div>    .meting-player-controls {</div><div>        padding: 10px;</div><div>    }</div><div>    </div><div>    .meting-progress-top {</div><div>        flex-direction: row;</div><div>        align-items: center;</div><div>        margin-bottom: 10px;</div><div>    }</div><div>    </div><div>    .meting-time-display {</div><div>        margin-top: 0;</div><div>        min-width: auto;</div><div>        text-align: right;</div><div>        font-size: 11px;</div><div>        margin-left: 10px;</div><div>    }</div><div>    </div><div>    .meting-controls-bottom {</div><div>        flex-direction: row;</div><div>        gap: 5px;</div><div>    }</div><div>    </div><div>    .meting-volume-container {</div><div>        width: auto;</div><div>        justify-content: flex-end;</div><div>    }</div><div>    </div><div>    .meting-volume-slider {</div><div>        flex: 1;</div><div>        max-width: 80px;</div><div>    }</div><div>    </div><div>    .meting-control-btn {</div><div>        font-size: 18px;</div><div>        margin: 0 3px;</div><div>        width: 28px;</div><div>        height: 28px;</div><div>    }</div><div>    </div><div>    .meting-play-pause {</div><div>        font-size: 28px;</div><div>        width: 36px;</div><div>        height: 36px;</div><div>    }</div><div>    </div><div>    .meting-toggle-player {</div><div>        top: -8px;</div><div>        right: -8px;</div><div>        width: 20px;</div><div>        height: 20px;</div><div>        font-size: 12px;</div><div>    }</div><div>    </div><div>    .meting-lyrics-container {</div><div>        font-size: 14px;</div><div>        padding: 8px;</div><div>        z-index: 800;</div><div>        line-height: 1.5;</div><div>    }</div><div>    </div><div>    /* 手机端播放列表样式 */</div><div>    .meting-playlist-container {</div><div>        max-height: 200px;</div><div>        border-radius: 10px;</div><div>        padding: 10px;</div><div>        bottom: calc(100% + 8px);</div><div>        background: rgba(60, 66, 64, 0.9);</div><div>    }</div><div>    </div><div>    .meting-playlist-header {</div><div>        margin-bottom: 10px;</div><div>        padding-bottom: 8px;</div><div>    }</div><div>    </div><div>    .meting-playlist-title {</div><div>        font-size: 14px;</div><div>    }</div><div>    </div><div>    .meting-playlist-count {</div><div>        font-size: 11px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item {</div><div>        padding: 10px 12px;</div><div>        border-radius: 6px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-index {</div><div>        margin-right: 12px;</div><div>        font-size: 12px;</div><div>        min-width: 20px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-title {</div><div>        font-size: 13px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-artist {</div><div>        font-size: 11px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-duration {</div><div>        font-size: 11px;</div><div>        min-width: 35px;</div><div>    }</div><div>    </div><div>    .meting-lyrics-container:not([style*="display: none"]) {</div><div>        height: auto;</div><div>    }</div><div>    </div><div>    .meting-lyrics-container[style*="display: none"] ~ .meting-player-container {</div><div>        bottom: 10px;</div><div>    }</div><div>}</div><div><br></div><div>/* 小屏手机适配 - 修改为左下角位置 */</div><div>@media screen and (max-width: 480px) {</div><div>    .meting-player-container {</div><div>        left: 5px;</div><div>        right: auto;</div><div>        bottom: 10px;</div><div>        max-width: 300px;</div><div>    }</div><div>/* 这个播放器来源blog.3e0.cn 使用请保留本标识 */    </div><div>    .meting-player-header {</div><div>        padding: 8px;</div><div>    }</div><div>    </div><div>    .meting-song-title {</div><div>        font-size: 12px;</div><div>    }</div><div>    </div><div>    .meting-song-artist {</div><div>        font-size: 10px;</div><div>    }</div><div>    </div><div>    .meting-control-btn {</div><div>        font-size: 16px;</div><div>        margin: 0 2px;</div><div>        width: 24px;</div><div>        height: 24px;</div><div>    }</div><div>    </div><div>    .meting-play-pause {</div><div>        font-size: 24px;</div><div>        width: 32px;</div><div>        height: 32px;</div><div>    }</div><div>    </div><div>    .meting-lyrics-btn,</div><div>    .meting-playlist-btn,</div><div>    .meting-mode-btn {</div><div>        font-size: 16px;</div><div>        margin-left: 5px;</div><div>        width: 20px;</div><div>        height: 20px;</div><div>    }</div><div>    </div><div>    .meting-time-display {</div><div>        font-size: 10px;</div><div>    }</div><div>    </div><div>    .meting-lyrics-container {</div><div>        font-size: 13px;</div><div>        padding: 5px;</div><div>        line-height: 1.5;</div><div>    }</div><div>    </div><div>    .meting-volume-slider {</div><div>        max-width: 60px;</div><div>    }</div><div>    </div><div>    /* 小屏手机播放列表样式 */</div><div>    .meting-playlist-container {</div><div>        max-height: 180px;</div><div>        padding: 8px;</div><div>        bottom: calc(100% + 5px);</div><div>        border-radius: 8px;</div><div>        background: rgba(60, 66, 64, 0.9);</div><div>    }</div><div>    </div><div>    .meting-playlist-item {</div><div>        padding: 8px 10px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-index {</div><div>        margin-right: 10px;</div><div>        font-size: 11px;</div><div>        min-width: 18px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-title {</div><div>        font-size: 12px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-artist {</div><div>        font-size: 10px;</div><div>    }</div><div>    </div><div>    .meting-playlist-item-duration {</div><div>        display: none;</div><div>    }</div><div>}</div><div></style></div><div><link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"></div><div><div class="meting-player-container"></div><div>    <div class="meting-player-main"></div><div>        <img class="meting-album-cover" src="" alt="专辑封面"></div><div>        <div class="meting-player-header"></div><div>            <div class="meting-song-info"></div><div>                <div class="meting-song-title">正在加载...</div></div><div>                <div class="meting-song-artist">请稍候</div></div><div>            </div></div><div>            <button class="meting-lyrics-btn">词</button></div><div>            <button class="meting-playlist-btn"><i class="fa fa-list"></i></button></div><div>            <button class="meting-mode-btn"><i class="fa fa-random"></i></button></div><div>        </div></div><div>        <div class="meting-player-controls"></div><div>            <div class="meting-progress-top"></div><div>                <div class="meting-progress-container"></div><div>                    <div class="meting-progress-bar"></div></div><div>                </div></div><div>                <div class="meting-time-display">00:00 / 00:00</div></div><div>            </div></div><div>            <div class="meting-controls-bottom"></div><div>                <div class="meting-control-buttons"></div><div>                    <button class="meting-control-btn meting-prev-btn"><i class="fa fa-step-backward"></i></button></div><div>                    <button class="meting-control-btn meting-play-pause"><i class="fa fa-play"></i></button></div><div>                    <button class="meting-control-btn meting-next-btn"><i class="fa fa-step-forward"></i></button></div><div>                </div></div><div>                <div class="meting-volume-container"></div><div>                    <button class="meting-volume-btn"><i class="fa fa-volume-up"></i></button></div><div>                    <input type="range" class="meting-volume-slider" min="0" max="100" value="80"></div><div>                </div></div><div>            </div></div><div>        </div></div><div>        <div class="meting-playlist-container"></div><div>            <div class="meting-playlist-header"></div><div>                <div class="meting-playlist-title">播放列表</div></div><div>                <div class="meting-playlist-count">0 首歌曲</div></div><div>            </div></div><div>            <div class="meting-playlist-items"></div></div><div>        </div></div><div>    </div></div><div>    <button class="meting-toggle-player"><i class="fa fa-minus"></i></button></div><div></div></div><div><br></div><div><div class="meting-lyrics-container"></div><div>    <div class="meting-lyrics-line">歌词加载中...</div></div><div></div></div><div><br></div><div><script></div><div>(function() {</div><div>    // 播放器状态</div><div>    const playerState = {</div><div>        playlist: [],</div><div>        currentIndex: 0,</div><div>        isPlaying: false,</div><div>        volume: 80,</div><div>        currentTime: 0,</div><div>        duration: 0,</div><div>        mode: 'random',</div><div>        minimized: false,</div><div>        lyricsVisible: true,</div><div>        lyricsAutoHide: true,</div><div>        lastPlayedSong: null,</div><div>        lastPlayedPosition: 0,</div><div>        autoPlayBlocked: false,</div><div>        lyrics: []</div><div>    };</div><div><br></div><div>    // DOM元素</div><div>    const elements = {</div><div>        playerContainer: document.querySelector('.meting-player-container'),</div><div>        playerMain: document.querySelector('.meting-player-main'),</div><div>        albumCover: document.querySelector('.meting-album-cover'),</div><div>        songTitle: document.querySelector('.meting-song-title'),</div><div>        songArtist: document.querySelector('.meting-song-artist'),</div><div>        playPauseBtn: document.querySelector('.meting-play-pause'),</div><div>        prevBtn: document.querySelector('.meting-prev-btn'),</div><div>        nextBtn: document.querySelector('.meting-next-btn'),</div><div>        progressContainer: document.querySelector('.meting-progress-container'),</div><div>        progressBar: document.querySelector('.meting-progress-bar'),</div><div>        timeDisplay: document.querySelector('.meting-time-display'),</div><div>        volumeBtn: document.querySelector('.meting-volume-btn'),</div><div>        volumeSlider: document.querySelector('.meting-volume-slider'),</div><div>        togglePlayerBtn: document.querySelector('.meting-toggle-player'),</div><div>        lyricsContainer: document.querySelector('.meting-lyrics-container'),</div><div>        lyricsLine: document.querySelector('.meting-lyrics-line'),</div><div>        playlistBtn: document.querySelector('.meting-playlist-btn'),</div><div>        playlistContainer: document.querySelector('.meting-playlist-container'),</div><div>        playlistItems: document.querySelector('.meting-playlist-items'),</div><div>        playlistTitle: document.querySelector('.meting-playlist-title'),</div><div>        playlistCount: document.querySelector('.meting-playlist-count'),</div><div>        modeBtn: document.querySelector('.meting-mode-btn'),</div><div>        lyricsBtn: document.querySelector('.meting-lyrics-btn')</div><div>    };</div><div><br></div><div>    // 音频元素</div><div>    const audio = new Audio();</div><div>    audio.volume = playerState.volume / 100;</div><div><br></div><div>    // 新增:HTML实体解码函数,解决&apos;显示问题</div><div>    function decodeHtmlEntities(text) {</div><div>        const textArea = document.createElement('textarea');</div><div>        textArea.innerHTML = text;</div><div>        return textArea.value;</div><div>    }</div><div><br></div><div>    // 从localStorage加载状态</div><div>    function loadPlayerState() {</div><div>        const savedState = localStorage.getItem('metingPlayerState');</div><div>        if (savedState) {</div><div>            const state = JSON.parse(savedState);</div><div>            playerState.currentIndex = state.currentIndex || 0;</div><div>            playerState.isPlaying = state.isPlaying || false;</div><div>            playerState.volume = state.volume || 80;</div><div>            playerState.currentTime = state.currentTime || 0;</div><div>            playerState.mode = state.mode || 'random';</div><div>            playerState.minimized = state.minimized || false;</div><div>            playerState.lyricsVisible = state.lyricsVisible !== undefined ? state.lyricsVisible : true;</div><div>            playerState.lyricsAutoHide = state.lyricsAutoHide !== undefined ? state.lyricsAutoHide : true;</div><div>            playerState.lastPlayedSong = state.lastPlayedSong || null;</div><div>            playerState.lastPlayedPosition = state.lastPlayedPosition || 0;</div><div>            </div><div>            // 应用保存的状态</div><div>            audio.volume = playerState.volume / 100;</div><div>            elements.volumeSlider.value = playerState.volume;</div><div>            </div><div>            if (playerState.minimized) {</div><div>                elements.playerContainer.classList.add('minimized');</div><div>                elements.togglePlayerBtn.innerHTML = '<i class="fa fa-plus"></i>';</div><div>            }</div><div>            </div><div>            // 强制同步歌词按钮和显示状态</div><div>            updateLyricsButton();</div><div>            updateLyricsVisibility();</div><div>            </div><div>            updateModeButton();</div><div>            updateVolumeIcon();</div><div>        }</div><div>    }</div><div><br></div><div>    // 保存状态到localStorage</div><div>    function savePlayerState() {</div><div>        playerState.currentTime = audio.currentTime;</div><div>        </div><div>        if (playerState.playlist.length > 0 && playerState.currentIndex >= 0) {</div><div>            const currentSong = playerState.playlist[playerState.currentIndex];</div><div>            playerState.lastPlayedSong = {</div><div>                id: currentSong.id || currentSong.name,</div><div>                name: currentSong.name,</div><div>                artist: currentSong.artist</div><div>            };</div><div>            playerState.lastPlayedPosition = audio.currentTime;</div><div>        }</div><div>        </div><div>        localStorage.setItem('metingPlayerState', JSON.stringify(playerState));</div><div>    }</div><div><br></div><div>    // 更新歌词按钮状态</div><div>    function updateLyricsButton() {</div><div>        if (playerState.lyricsVisible) {</div><div>            elements.lyricsBtn.classList.add('active');</div><div>        } else {</div><div>            elements.lyricsBtn.classList.remove('active');</div><div>        }</div><div>    }</div><div><br></div><div>    // 修复歌词开启后播放不显示的问题:简化判断逻辑,确保播放时优先显示</div><div>    function updateLyricsVisibility() {</div><div>        // 只要歌词开启、未被自动播放阻止,且音频有资源,播放时就显示</div><div>        const canShowLyrics = playerState.lyricsVisible && !playerState.autoPlayBlocked && audio.src;</div><div>        if (playerState.isPlaying && canShowLyrics) {</div><div>            elements.lyricsContainer.style.display = 'block';</div><div>            adjustPlayerPosition();</div><div>        } else {</div><div>            elements.lyricsContainer.style.display = 'none';</div><div>            resetPlayerPosition();</div><div>        }</div><div>    }</div><div><br></div><div>    // 调整播放器位置(确保在歌词上方)</div><div>    function adjustPlayerPosition() {</div><div>        if (window.matchMedia('(max-width: 768px)').matches) {</div><div>            const lyricsHeight = elements.lyricsContainer.offsetHeight;</div><div>            elements.playerContainer.style.bottom = (lyricsHeight + 10) + 'px';</div><div>        }</div><div>    }</div><div><br></div><div>    // 重置播放器位置(歌词隐藏时)</div><div>    function resetPlayerPosition() {</div><div>        if (window.matchMedia('(max-width: 768px)').matches) {</div><div>            elements.playerContainer.style.bottom = '10px';</div><div>        }</div><div>    }</div><div><br></div><div>    // 更新模式按钮</div><div>    function updateModeButton() {</div><div>        switch(playerState.mode) {</div><div>            case 'random':</div><div>                elements.modeBtn.innerHTML = '<i class="fa fa-random"></i>';</div><div>                break;</div><div>            case 'sequential':</div><div>                elements.modeBtn.innerHTML = '<i class="fa fa-arrow-right"></i>';</div><div>                break;</div><div>            case 'loop':</div><div>                elements.modeBtn.innerHTML = '<i class="fa fa-repeat"></i>';</div><div>                break;</div><div>        }</div><div>    }</div><div><br></div><div>    // 更新音量图标</div><div>    function updateVolumeIcon() {</div><div>        const volume = elements.volumeSlider.value;</div><div>        let iconClass = 'fa-volume-up';</div><div>        </div><div>        if (volume == 0) {</div><div>            iconClass = 'fa-volume-off';</div><div>        } else if (volume < 33) {</div><div>            iconClass = 'fa-volume-down';</div><div>        }</div><div>        </div><div>        elements.volumeBtn.innerHTML = `<i class="fa ${iconClass}"></i>`;</div><div>    }</div><div><br></div><div>    // 从MetingAPI获取播放列表</div><div>    async function fetchPlaylist() {</div><div>        try {</div><div>            const response = await fetch('https://music.3e0.cn/?server=netease&type=playlist&id=3778678');</div><div>            const playlist = await response.json();</div><div>            </div><div>            if (Array.isArray(playlist) && playlist.length > 0) {</div><div>                playerState.playlist = playlist;</div><div>                renderPlaylist();</div><div>                </div><div>                // 检查是否有上次播放的歌曲记录</div><div>                let targetIndex = 0;</div><div>                let targetPosition = 0;</div><div>                </div><div>                if (playerState.lastPlayedSong) {</div><div>                    const foundIndex = playlist.findIndex(song => </div><div>                        (song.id && song.id === playerState.lastPlayedSong.id) || </div><div>                        (song.name === playerState.lastPlayedSong.name && song.artist === playerState.lastPlayedSong.artist)</div><div>                    );</div><div>                    </div><div>                    if (foundIndex !== -1) {</div><div>                        targetIndex = foundIndex;</div><div>                        targetPosition = playerState.lastPlayedPosition;</div><div>                    }</div><div>                } else if (playerState.currentIndex >= 0 && playerState.currentIndex < playlist.length) {</div><div>                    targetIndex = playerState.currentIndex;</div><div>                    targetPosition = playerState.currentTime;</div><div>                }</div><div>                </div><div>                loadSong(targetIndex, targetPosition);</div><div>                </div><div>                if (playerState.isPlaying) {</div><div>                    setTimeout(() => {</div><div>                        audio.play().catch(e => {</div><div>                            console.log('自动播放被阻止:', e);</div><div>                            playerState.autoPlayBlocked = true;</div><div>                            playerState.isPlaying = false;</div><div>                            updatePlayButtonState();</div><div>                            savePlayerState();</div><div>                        });</div><div>                    }, 500);</div><div>                }</div><div>            } else {</div><div>                console.error('获取播放列表失败');</div><div>                elements.songTitle.textContent = '获取播放列表失败';</div><div>            }</div><div>        } catch (error) {</div><div>            console.error('获取播放列表出错:', error);</div><div>            elements.songTitle.textContent = '获取播放列表出错';</div><div>        }</div><div>    }</div><div><br></div><div>    // 渲染播放列表</div><div>    function renderPlaylist() {</div><div>        elements.playlistItems.innerHTML = '';</div><div>        elements.playlistCount.textContent = `${playerState.playlist.length} 首歌曲`;</div><div>        </div><div>        playerState.playlist.forEach((song, index) => {</div><div>            const item = document.createElement('div');</div><div>            item.className = 'meting-playlist-item';</div><div>            if (index === playerState.currentIndex) {</div><div>                item.classList.add('playing');</div><div>            }//本播放器来自blog.3e0.cn 使用请保留本标识</div><div>            </div><div>            let durationText = '';</div><div>            if (song.duration) {</div><div>                const minutes = Math.floor(song.duration / 60);</div><div>                const seconds = Math.floor(song.duration % 60);</div><div>                durationText = `${minutes}:${seconds.toString().padStart(2, '0')}`;</div><div>            }</div><div>            </div><div>            item.innerHTML = `</div><div>                <div class="meting-playlist-item-index">${index + 1}</div></div><div>                <div class="meting-playlist-item-info"></div><div>                    <div class="meting-playlist-item-title">${decodeHtmlEntities(song.name)}</div></div><div>                    <div class="meting-playlist-item-artist">${decodeHtmlEntities(song.artist)}</div></div><div>                </div></div><div>                <div class="meting-playlist-item-duration">${durationText}</div></div><div>            `;</div><div>            </div><div>            item.addEventListener('click', () => {</div><div>                playerState.isPlaying = true;</div><div>                playerState.autoPlayBlocked = false;</div><div>                updatePlayButtonState();</div><div>                updateLyricsVisibility();</div><div>                </div><div>                loadSong(index);</div><div>                audio.play().catch(e => {</div><div>                    console.log('播放被阻止:', e);</div><div>                    playerState.autoPlayBlocked = true;</div><div>                    playerState.isPlaying = false;</div><div>                    updatePlayButtonState();</div><div>                    updateLyricsVisibility();</div><div>                    savePlayerState();</div><div>                });</div><div>            });</div><div>            </div><div>            elements.playlistItems.appendChild(item);</div><div>        });</div><div>        </div><div>        if (elements.playlistContainer.classList.contains('show')) {</div><div>            scrollToCurrentSong();</div><div>        }</div><div>    }</div><div><br></div><div>    // 滚动到当前播放的歌曲</div><div>    function scrollToCurrentSong() {</div><div>        const currentItem = elements.playlistItems.children[playerState.currentIndex];</div><div>        if (currentItem) {</div><div>            currentItem.scrollIntoView({ behavior: 'smooth', block: 'nearest' });</div><div>        }</div><div>    }</div><div><br></div><div>    // 加载歌曲</div><div>    function loadSong(index, position = 0) {</div><div>        if (index < 0 || index >= playerState.playlist.length) return;</div><div>        </div><div>        const song = playerState.playlist[index];</div><div>        playerState.currentIndex = index;</div><div>        </div><div>        // 解码歌曲名和歌手名中的HTML实体</div><div>        elements.songTitle.textContent = decodeHtmlEntities(song.name);</div><div>        elements.songArtist.textContent = decodeHtmlEntities(song.artist);</div><div>        </div><div>        if (song.pic) {</div><div>            elements.albumCover.src = song.pic;</div><div>        }</div><div>        </div><div>        audio.src = song.url;</div><div>        audio.load();</div><div>        </div><div>        audio.onloadedmetadata = function() {</div><div>            if (position > 0 && position < audio.duration) {</div><div>                audio.currentTime = position;</div><div>                playerState.currentTime = position;</div><div>            }</div><div>            </div><div>            updatePlayButtonState();</div><div>            if (playerState.isPlaying) {</div><div>                audio.play().catch(e => {</div><div>                    console.log('播放被阻止:', e);</div><div>                    playerState.autoPlayBlocked = true;</div><div>                    playerState.isPlaying = false;</div><div>                    updatePlayButtonState();</div><div>                    updateLyricsVisibility();</div><div>                    savePlayerState();</div><div>                });</div><div>            }</div><div>        };</div><div>        </div><div>        fetchLyrics(song.lrc);</div><div>        </div><div>        const items = document.querySelectorAll('.meting-playlist-item');</div><div>        items.forEach((item, i) => {</div><div>            if (i === index) {</div><div>                item.classList.add('playing');</div><div>            } else {</div><div>                item.classList.remove('playing');</div><div>            }</div><div>        });</div><div>        </div><div>        scrollToCurrentSong();</div><div>        savePlayerState();</div><div>        updateLyricsVisibility();</div><div>        updateLyricsButton();</div><div>    }</div><div><br></div><div>    // 获取歌词</div><div>    async function fetchLyrics(url) {</div><div>        try {</div><div>            const response = await fetch(url);</div><div>            const text = await response.text();</div><div>            parseLyrics(text);</div><div>        } catch (error) {</div><div>            console.error('获取歌词失败:', error);</div><div>            elements.lyricsLine.textContent = '歌词加载失败';</div><div>            adjustPlayerPosition();</div><div>        }</div><div>    }</div><div><br></div><div>    // 解析歌词 - 应用HTML实体解码</div><div>    function parseLyrics(text) {</div><div>        const lines = text.split('n');</div><div>        const lyrics = [];</div><div>        const regex = /[(d+):(d+).(d+)](.*)/;</div><div>        </div><div>        lines.forEach(line => {</div><div>            const match = line.match(regex);</div><div>            if (match) {</div><div>                const minutes = parseInt(match[1]);</div><div>                const seconds = parseInt(match[2]);</div><div>                const milliseconds = parseInt(match[3]);</div><div>                // 解码歌词文本中的HTML实体</div><div>                const text = decodeHtmlEntities(match[4].trim());</div><div>                const time = minutes * 60 + seconds + milliseconds / 100;</div><div>                lyrics.push({ time, text });</div><div>            }</div><div>        });</div><div>        </div><div>        lyrics.sort((a, b) => a.time - b.time);</div><div>        playerState.lyrics = lyrics;</div><div>        elements.lyricsLine.textContent = lyrics.length > 0 ? lyrics[0].text : '暂无歌词';</div><div>        adjustPlayerPosition();</div><div>    }</div><div><br></div><div>    // 更新歌词显示</div><div>    function updateLyrics() {</div><div>        if (!playerState.lyrics || !playerState.lyricsVisible || playerState.autoPlayBlocked || !playerState.isPlaying) return;</div><div>        </div><div>        const currentTime = audio.currentTime;</div><div>        let currentLine = '';</div><div>        </div><div>        for (let i = playerState.lyrics.length - 1; i >= 0; i--) {</div><div>            if (currentTime >= playerState.lyrics[i].time) {</div><div>                currentLine = playerState.lyrics[i].text;</div><div>                break;</div><div>            }</div><div>        }</div><div>        </div><div>        elements.lyricsLine.textContent = currentLine || '♪';</div><div>        adjustPlayerPosition();</div><div>    }</div><div><br></div><div>    // 同步播放按钮状态</div><div>    function updatePlayButtonState() {</div><div>        if (playerState.isPlaying) {</div><div>            elements.playPauseBtn.innerHTML = '<i class="fa fa-pause"></i>';</div><div>            elements.playerMain.classList.add('playing');</div><div>        } else {</div><div>            elements.playPauseBtn.innerHTML = '<i class="fa fa-play"></i>';</div><div>            elements.playerMain.classList.remove('playing');</div><div>        }</div><div>    }</div><div><br></div><div>    // 修复播放后歌词不显示:播放/暂停时立即同步状态</div><div>    function togglePlay() {</div><div>        if (audio.paused) {</div><div>            audio.play().then(() => {</div><div>                playerState.isPlaying = true;</div><div>                playerState.autoPlayBlocked = false;</div><div>            }).catch(e => {</div><div>                console.log('播放被阻止:', e);</div><div>                playerState.autoPlayBlocked = true;</div><div>                playerState.isPlaying = false;</div><div>            });</div><div>        } else {</div><div>            audio.pause();</div><div>            playerState.isPlaying = false;</div><div>        }</div><div>        // 立即更新状态,不等待异步结果</div><div>        setTimeout(() => {</div><div>            updatePlayButtonState();</div><div>            updateLyricsVisibility();</div><div>            savePlayerState();</div><div>        }, 0);</div><div>    }</div><div><br></div><div>    // 切换歌词显示/隐藏</div><div>    function toggleLyrics() {</div><div>        playerState.lyricsVisible = !playerState.lyricsVisible;</div><div>        updateLyricsVisibility();</div><div>        updateLyricsButton();</div><div>        savePlayerState();</div><div>    }</div><div><br></div><div>    // 下一首</div><div>    function nextSong() {</div><div>        let nextIndex;</div><div>        switch(playerState.mode) {</div><div>            case 'random':</div><div>                nextIndex = Math.floor(Math.random() * playerState.playlist.length);</div><div>                break;</div><div>            case 'sequential':</div><div>                nextIndex = (playerState.currentIndex + 1) % playerState.playlist.length;</div><div>                break;</div><div>            case 'loop':</div><div>                nextIndex = playerState.currentIndex;</div><div>                break;</div><div>        }</div><div>        </div><div>        playerState.isPlaying = true;</div><div>        playerState.autoPlayBlocked = false;</div><div>        updatePlayButtonState();</div><div>        updateLyricsVisibility();</div><div>        </div><div>        loadSong(nextIndex);</div><div>        audio.play().catch(e => {</div><div>            console.log('播放被阻止:', e);</div><div>            playerState.autoPlayBlocked = true;</div><div>            playerState.isPlaying = false;</div><div>            updatePlayButtonState();</div><div>            updateLyricsVisibility();</div><div>            savePlayerState();</div><div>        });</div><div>    }</div><div><br></div><div>    // 上一首</div><div>    function prevSong() {</div><div>        let prevIndex;</div><div>        switch(playerState.mode) {</div><div>            case 'random':</div><div>                prevIndex = Math.floor(Math.random() * playerState.playlist.length);</div><div>                break;</div><div>            case 'sequential':</div><div>                prevIndex = (playerState.currentIndex - 1 + playerState.playlist.length) % playerState.playlist.length;</div><div>                break;</div><div>            case 'loop':</div><div>                prevIndex = playerState.currentIndex;</div><div>                break;</div><div>        }</div><div>        </div><div>        playerState.isPlaying = true;</div><div>        playerState.autoPlayBlocked = false;</div><div>        updatePlayButtonState();</div><div>        updateLyricsVisibility();</div><div>        </div><div>        loadSong(prevIndex);</div><div>        audio.play().catch(e => {</div><div>            console.log('播放被阻止:', e);</div><div>            playerState.autoPlayBlocked = true;</div><div>            playerState.isPlaying = false;</div><div>            updatePlayButtonState();</div><div>            updateLyricsVisibility();</div><div>            savePlayerState();</div><div>        });</div><div>    }</div><div><br></div><div>    // 切换播放模式</div><div>    function toggleMode() {</div><div>        const modes = ['random', 'sequential', 'loop'];</div><div>        const currentIndex = modes.indexOf(playerState.mode);</div><div>        playerState.mode = modes[(currentIndex + 1) % modes.length];</div><div>        updateModeButton();</div><div>        savePlayerState();</div><div>    }</div><div><br></div><div>    // 切换播放器最小化状态</div><div>    function toggleMinimize() {</div><div>        playerState.minimized = !playerState.minimized;</div><div>        </div><div>        if (playerState.minimized) {</div><div>            elements.playerContainer.classList.add('minimized');</div><div>            elements.togglePlayerBtn.innerHTML = '<i class="fa fa-plus"></i>';</div><div>            elements.playlistContainer.classList.remove('show');</div><div>        } else {</div><div>            elements.playerContainer.classList.remove('minimized');</div><div>            elements.togglePlayerBtn.innerHTML = '<i class="fa fa-minus"></i>';</div><div>        }</div><div>        </div><div>        savePlayerState();</div><div>    }</div><div><br></div><div>    // 切换播放列表显示</div><div>    function togglePlaylist() {</div><div>        if (playerState.minimized) {</div><div>            toggleMinimize();</div><div>        }</div><div>        elements.playlistContainer.classList.toggle('show');</div><div>        </div><div>        if (elements.playlistContainer.classList.contains('show')) {</div><div>            setTimeout(() => {</div><div>                scrollToCurrentSong();</div><div>            }, 0);</div><div>        }</div><div>    }</div><div><br></div><div>    // 更新进度条</div><div>    function updateProgress() {</div><div>        const percent = (audio.currentTime / audio.duration) * 100;</div><div>        elements.progressBar.style.width = `${percent}%`;</div><div>        </div><div>        const currentMinutes = Math.floor(audio.currentTime / 60);</div><div>        const currentSeconds = Math.floor(audio.currentTime % 60);</div><div>        const durationMinutes = Math.floor(audio.duration / 60);</div><div>        const durationSeconds = Math.floor(audio.duration % 60);</div><div>        </div><div>        elements.timeDisplay.textContent = </div><div>            `${currentMinutes.toString().padStart(2, '0')}:${currentSeconds.toString().padStart(2, '0')} / ${durationMinutes.toString().padStart(2, '0')}:${durationSeconds.toString().padStart(2, '0')}`;</div><div>        </div><div>        updateLyrics();</div><div>        </div><div>        if (Math.floor(audio.currentTime) % 5 === 0) {</div><div>            savePlayerState();</div><div>        }</div><div>    }</div><div><br></div><div>    // 设置进度</div><div>    function setProgress(e) {</div><div>        const width = elements.progressContainer.clientWidth;</div><div>        const clickX = e.offsetX;</div><div>        const duration = audio.duration;</div><div>        </div><div>        audio.currentTime = (clickX / width) * duration;</div><div>        savePlayerState();</div><div>    }</div><div><br></div><div>    // 设置音量</div><div>    function setVolume() {</div><div>        const volume = elements.volumeSlider.value;</div><div>        audio.volume = volume / 100;</div><div>        playerState.volume = volume;</div><div>        </div><div>        updateVolumeIcon();</div><div>        savePlayerState();</div><div>    }</div><div><br></div><div>    // 初始化事件监听</div><div>    function initEventListeners() {</div><div>        elements.playPauseBtn.addEventListener('click', togglePlay);</div><div>        elements.prevBtn.addEventListener('click', prevSong);</div><div>        elements.nextBtn.addEventListener('click', nextSong);</div><div>        elements.progressContainer.addEventListener('click', setProgress);</div><div>        elements.volumeSlider.addEventListener('input', setVolume);</div><div>        elements.togglePlayerBtn.addEventListener('click', toggleMinimize);</div><div>        elements.lyricsBtn.addEventListener('click', toggleLyrics);</div><div>        elements.playlistBtn.addEventListener('click', togglePlaylist);</div><div>        elements.modeBtn.addEventListener('click', toggleMode);</div><div>        </div><div>        audio.addEventListener('timeupdate', updateProgress);</div><div>        audio.addEventListener('ended', nextSong);</div><div>        </div><div>        // 监听音频原生事件,确保状态100%同步</div><div>        audio.addEventListener('play', () => {</div><div>            playerState.isPlaying = true;</div><div>            updatePlayButtonState();</div><div>            updateLyricsVisibility();</div><div>        });</div><div>        audio.addEventListener('pause', () => {</div><div>            playerState.isPlaying = false;</div><div>            updatePlayButtonState();</div><div>            updateLyricsVisibility();</div><div>        });</div><div>        </div><div>        window.addEventListener('beforeunload', savePlayerState);</div><div>        document.addEventListener('visibilitychange', function() {</div><div>            if (document.hidden) {</div><div>                savePlayerState();</div><div>            }</div><div>        });</div><div>        </div><div>        window.addEventListener('resize', function() {</div><div>            updateLyricsVisibility();</div><div>        });</div><div><br></div><div>        const lyricsObserver = new MutationObserver(() => {</div><div>            adjustPlayerPosition();</div><div>        });</div><div>        lyricsObserver.observe(elements.lyricsLine, { childList: true, characterData: true, subtree: true });</div><div>    }</div><div><br></div><div>    // 初始化播放器</div><div>    function initPlayer() {</div><div>        loadPlayerState();</div><div>        initEventListeners();</div><div>        fetchPlaylist();</div><div>        updatePlayButtonState();</div><div>        updateLyricsButton();</div><div>    }</div><div><br></div><div>    // 启动播放器</div><div>    initPlayer();</div><div>})();</div><div></script>
打赏列表
分享文章

1 条评论

  1. qpoommnn@qq.com 普通用户

    1111

    回复 qpoommnn@qq.com