新年专属网页悬浮音乐播放器代码

上些日子给网站做了有关于新年红的配色,今天就总觉得差点什么,索性写了一个播放器。过年了放上会更加有新年氛围,提前祝大家新年快乐!
功能说明
响应式布局:手机端底部居中(支持收缩 / 展开),电脑端左下角固定显示
核心功能:播放 / 暂停、下一曲切换、单曲结束自动切歌,随机切歌不重复
体验优化:刷新 / 页面跳转精准续播、无闪烁无冗余样式、手机端点击空白处收缩展开
样式特色:新年红金配色、悬浮阴影效果、按钮交互反馈,适配中文字体无乱码
兼容处理:突破浏览器自动播放限制,兼容微信 X5 内核,全局样式无冲突
使用说明
1. 代码部署
将以下完整代码直接粘贴到 Typecho 主题自定义 HTML/PHP 文件中(如页脚文件footer.php),建议放在标签前。
<style>
#musicPlayer {
position: fixed;
bottom: 10px;
z-index: 999;
display: flex;
align-items: center;
gap: 12px;
padding: 8px 20px;
background: rgba(216, 0, 15, 0.9);
border-radius: 50px;
box-shadow: 0 0 20px rgba(250, 108, 0, 0.8);
-webkit-tap-highlight-color: transparent;
box-sizing: border-box;
border: 2px solid #dc8f03;
left: 50%;
transform: translateX(-50%);
min-width: fit-content;
transition: all 0.3s ease-in-out;
}
@media screen and (min-width: 768px) {
#musicPlayer {
left: 15px;
transform: translateX(0);
}
#musicInfo {
display: block !important;
}
}
@media screen and (max-width: 767px) {
#musicPlayer.shrink {
padding: 8px;
}
#musicInfo {
display: block;
transition: all 0.3s ease-in-out;
}
#musicPlayer.shrink #musicInfo {
display: none;
}
}
.music-btn {
width: 42px;
height: 42px;
border-radius: 50%;
border: none;
outline: none;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: bold;
color: #d8000f;
background: #dc8f03;
transition: all 0.3s ease;
box-shadow: 0 0 10px rgba(250, 108, 0, 0.5);
}
.music-btn:hover {
background: #fff;
color: #d8000f;
box-shadow: 0 0 15px rgba(250, 108, 0, 1);
}
.music-btn:active {
transform: scale(0.95);
}
#musicInfo {
color: #fff;
font-size: 13px;
font-family: "Microsoft YaHei", sans-serif;
white-space: nowrap;
line-height: 1.2;
}
#musicInfo span {
color: #ffd700;
font-weight: 500;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
</style>
<div id="musicPlayer">
<audio id="bgMusic" preload="auto" style="display: none;"></audio>
<button id="playBtn" class="music-btn">播放</button>
<button id="nextBtn" class="music-btn">下一曲</button>
<div id="musicInfo">
<span id="playStatus">暂停播放</span>:<span id="songName"></span> - <span id="singerName"></span>
</div>
</div>
<script>
window.addEventListener('load', function() {
const audio = document.getElementById('bgMusic');
const playBtn = document.getElementById('playBtn');
const nextBtn = document.getElementById('nextBtn');
const playStatusEl = document.getElementById('playStatus');
const songNameEl = document.getElementById('songName');
const singerNameEl = document.getElementById('singerName');
const musicPlayer = document.getElementById('musicPlayer');
const musicList = [
{ src: '/UGC/1.mp3', name: '《张灯结彩》', singer: '王二妮、阿宝' },
{ src: '/UGC/2.mp3', name: '《恭喜发财》', singer: '刘德华' },
{ src: '/UGC/3.mp3', name: '《新年大吉》', singer: '祁隆' }
];
let lastIndex = -1;
let isPlaying = false;
const CACHE_KEY = 'music_play_state';
let isInitiated = false;
let isShrinked = false;
function updateStatus() {
const statusText = isPlaying ? '正在播放' : '暂停播放';
playStatusEl.innerText = statusText;
playBtn.innerText = isPlaying ? '暂停' : '播放';
}
function updateMusicInfo(index) {
const song = musicList[index];
songNameEl.innerText = song.name;
singerNameEl.innerText = song.singer;
}
function getRandomIndex() {
let randomIndex;
do {
randomIndex = Math.floor(Math.random() * musicList.length);
} while (randomIndex === lastIndex && musicList.length > 1);
lastIndex = randomIndex;
return randomIndex;
}
function saveState() {
const currentIndex = musicList.findIndex(item => item.src === audio.src);
const state = {
isPlaying,
index: currentIndex > -1 ? currentIndex : 0,
time: audio.currentTime,
lastIndex
};
sessionStorage.setItem(CACHE_KEY, JSON.stringify(state));
}
function restoreState() {
const cache = sessionStorage.getItem(CACHE_KEY);
if (!cache) return false;
try {
const state = JSON.parse(cache);
audio.src = musicList[state.index].src;
audio.currentTime = state.time;
lastIndex = state.lastIndex;
isPlaying = state.isPlaying;
updateMusicInfo(state.index);
return true;
} catch (e) {
sessionStorage.removeItem(CACHE_KEY);
return false;
}
}
function toggleShrink() {
if (window.innerWidth > 767) return;
isShrinked = !isShrinked;
musicPlayer.classList.toggle('shrink', isShrinked);
}
function playCore() {
audio.muted = true;
audio.play().then(() => {
isPlaying = true;
updateStatus();
setTimeout(() => audio.muted = false, 100);
isInitiated = true;
saveState();
if (window.innerWidth <= 767 && !isShrinked) {
isShrinked = true;
musicPlayer.classList.add('shrink');
}
}).catch(err => {
isPlaying = false;
updateStatus();
});
}
function playMusic() {
if (!audio.src) {
const index = getRandomIndex();
audio.src = musicList[index].src;
updateMusicInfo(index);
}
playCore();
}
function pauseMusic() {
audio.pause();
isPlaying = false;
updateStatus();
saveState();
}
function togglePlay() {
if (window.innerWidth <= 767 && isShrinked) {
toggleShrink();
}
isPlaying ? pauseMusic() : playMusic();
}
function playNext() {
if (window.innerWidth <= 767 && isShrinked) {
toggleShrink();
}
const index = getRandomIndex();
audio.src = musicList[index].src;
updateMusicInfo(index);
audio.currentTime = 0;
playCore();
setTimeout(() => {
if (window.innerWidth <= 767 && !isShrinked) {
isShrinked = true;
musicPlayer.classList.add('shrink');
}
}, 2000);
}
playBtn.addEventListener('click', togglePlay);
playBtn.addEventListener('touchstart', (e) => { e.preventDefault(); togglePlay(); });
nextBtn.addEventListener('click', playNext);
nextBtn.addEventListener('touchstart', (e) => { e.preventDefault(); playNext(); });
musicPlayer.addEventListener('click', (e) => {
if (e.target === musicPlayer && window.innerWidth <= 767) {
toggleShrink();
}
});
musicPlayer.addEventListener('touchstart', (e) => {
if (e.target === musicPlayer && window.innerWidth <= 767) {
e.preventDefault();
toggleShrink();
}
}, { passive: false });
audio.addEventListener('ended', playNext);
audio.addEventListener('timeupdate', saveState);
window.addEventListener('resize', () => {
if (window.innerWidth > 767) {
musicPlayer.classList.remove('shrink');
}
});
const hasCache = restoreState();
if (hasCache) {
isPlaying && playCore();
} else {
playMusic();
}
function initOnUserAction() {
if (isInitiated) return;
playMusic();
document.removeEventListener('click', initOnUserAction);
document.removeEventListener('touchstart', initOnUserAction);
}
document.addEventListener('click', initOnUserAction);
document.addEventListener('touchstart', initOnUserAction, { passive: false });
});
</script>2. 音乐文件配置
将 MP3 音乐文件上传至网站/UGC/目录(若无该目录请自行创建)
如需修改音乐文件路径 / 添加 / 替换歌曲,直接修改代码中musicList数组即可,格式如下:
const musicList = [
{ src: '音乐文件路径', name: '歌曲名', singer: '歌手名' },
// 按需添加更多歌曲
];3. 基础操作
电脑端:直接点击「播放 / 暂停」「下一曲」按钮操作,全程显示歌曲信息
手机端:
点击按钮自动展开播放器,播放后 2 秒自动收缩
点击播放器空白处,可手动切换收缩 / 展开状态
切歌时自动展开显示新歌曲信息,2 秒后恢复收缩

评论区(4条评论)
动手能力很强,羡慕会写代码的大神,想咋整都行。
喜庆