一、前言
很多博主都会给自己的 Halo 博客添加悬浮音乐播放器,但传统播放器只能固定播放单一歌单,长期使用容易审美疲劳、听感单调。
本次在原有毛玻璃悬浮、可拖动、贴边自动隐藏播放器的基础上,进行全方位功能升级,重磅实现按星期自动切换歌单功能,一周七天每天自动更换不同歌单.
二、升级前后功能对比
本次升级100% 兼容旧版所有交互功能,仅新增核心能力、优化播放稳定性,无功能删减。
三、新旧代码核心改动详解
为方便大家理解升级逻辑,下面详细拆解本次所有修改点,每一处改动都对应专属功能优化。
1. HTML 结构优化:给播放器添加唯一标识
旧版问题:iframe 播放地址写死,无唯一标识,无法通过代码动态修改歌单。
旧版代码片段:
<iframe
src="https://music.163.com/outchain/player?type=0&id=12616213453&auto=0&height=100&bg=ffffff&fg=333333&mini=true"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
style="border: none; position: relative; z-index: 1;">
</iframe>新版优化:为 iframe 添加专属 ID music-iframe,让 JS 代码可以精准定位播放器,实现动态换歌单。
<iframe
id="music-iframe"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
style="border: none; position: relative; z-index: 1;">
</iframe>2. 新增核心配置:7天歌单自定义数组
新版新增可视化歌单配置区,无需懂代码,直接修改数字即可更换每日歌单。
// 核心配置:周日 ~ 周六 每日歌单ID
const dailyPlaylistIds = [
2561781141, // 周日
4985993055, // 周一
12616213453, // 周二
2561781141, // 周三
6665830498, // 周四
3120089590, // 周五
2561781141 // 周六
];关键规则(必看):
数组顺序严格对应:周日 → 周一 → 周二 → 周三 → 周四 → 周五 → 周六
仅支持网易云公开歌单,私密歌单、含 VIP/灰色版权歌曲的歌单,外链无法播放
可自由替换为自己的歌单 ID,支持自定义7组不同歌单
3. 新增自动切换核心函数
新增 setDailyPlaylist() 函数,实现「获取当日星期 → 匹配对应歌单 → 自动加载播放」的完整逻辑。
// 根据当天星期几自动加载对应歌单
function setDailyPlaylist() {
const today = new Date().getDay(); // 0=周日、1=周一 ... 6=周六
const playlistId = dailyPlaylistIds[today];
// 动态拼接合规网易云外链播放地址
const src = `https://music.163.com/outchain/player?type=0&id=${playlistId}&auto=1&height=100&bg=ffffff&fg=333333&mini=true`;
iframe.src = src;
}
// 页面加载自动执行,初始化当日歌单
setDailyPlaylist();小白通俗解释:
网页打开瞬间,代码自动识别今天是星期几
自动调取预设好的当日歌单 ID
自动生成合规播放链接,加载对应歌单
4. 修复播放故障,优化稳定性
针对旧版普遍存在的播放失效问题,做了两点关键修复:
将原静态固定播放地址,改为动态拼接合规外链接口,适配网易云最新外链规则
优化
auto=1播放参数,平衡浏览器拦截与播放体验,大幅降低播放失败概率规避 VIP、版权歌曲拦截问题,只要歌单合规即可稳定播放
5. 完整保留旧版所有交互功能
本次升级未修改任何拖动、隐藏逻辑:
支持任意位置拖动悬浮播放器
贴边自动隐藏、鼠标悬浮自动弹出
播放区域可正常点击操作,拖动与播放互不冲突
四、一键安装配置教程
步骤1:复制新版完整代码
下方为最终成品代码,集成所有升级功能,直接复制即可使用:
<!-- 仅最右侧边缘自动缩回 · 极简毛玻璃网易云悬浮播放器(带每日歌单切换) -->
<div id="music-drag-container" style="position: fixed; bottom: 24px; right: 8px; z-index: 9999; width: 290px; height: 90px; transition: transform 0.3s ease-in-out;">
<!-- 拖动手柄:默认透明,鼠标移上去时才变为可拖动 -->
<div id="drag-handle" style="position: absolute; top: 0; left: 0; width: 95%; height: 95%; z-index: 2; pointer-events: none; cursor: default;"></div>
<!-- 播放器本体 -->
<div style="position: absolute; top: 0; left: 0; width: 90; height: 120%; border-radius: 16px; overflow: hidden; background: rgba(255,255,255,0.95); backdrop-filter: blur(10px); box-shadow: 0 4px 20px rgba(0,0,0,0.08); display: flex; align-items: center; justify-content: center; border: 1px solid rgba(0,0,0,0.05);">
<iframe
id="music-iframe"
width="100%"
height="100%"
frameborder="0"
allowfullscreen
style="border: none; position: relative; z-index: 1;">
</iframe>
</div>
</div>
<script>
const container = document.getElementById('music-drag-container');
const handle = document.getElementById('drag-handle');
const iframe = document.getElementById('music-iframe');
let isDragging = false;
let offsetX, offsetY;
let isHidden = false;
let isOverIframe = false;
let hideTimer = null; // 自动缩回的定时器
// ========== 【核心修改:每日歌单配置】 ==========
// 请把这里的ID替换成你自己的歌单ID,顺序是 周日~周六
const dailyPlaylistIds = [
111111111, // 周日
222222222, // 周一
333333333, // 周二
444444444, // 周三
555555555, // 周四
666666666, // 周五
777777777 // 周六
];
// 根据当天星期几,设置对应的歌单
function setDailyPlaylist() {
const today = new Date().getDay(); // 0=周日, 1=周一 ... 6=周六
const playlistId = dailyPlaylistIds[today];
// 构建网易云播放器链接,auto=1允许自动播放
const src = `https://music.163.com/outchain/player?type=0&id=${playlistId}&auto=1&height=100&bg=ffffff&fg=333333&mini=true`;
iframe.src = src;
}
// 页面加载时,立即设置当天的歌单
setDailyPlaylist();
// 1. 鼠标进入播放器区域:取消缩回,启用拖动
container.addEventListener('mouseenter', function(e) {
// 鼠标进入时,清除自动缩回定时器
if (hideTimer) clearTimeout(hideTimer);
// 如果是隐藏状态,鼠标进入就自动弹出
if (isHidden) {
container.style.transform = 'translateX(0)';
isHidden = false;
}
// 只有鼠标不在iframe区域时,才启用拖动
if (!isOverIframe) {
handle.style.pointerEvents = 'auto';
handle.style.cursor = 'move';
}
});
// 2. 鼠标离开播放器区域:仅在最右侧(窗口宽度99%以上)自动缩回
container.addEventListener('mouseleave', function() {
handle.style.pointerEvents = 'none';
handle.style.cursor = 'default';
const playerRight = container.offsetLeft + container.offsetWidth;
const windowWidth = window.innerWidth ;
if (playerRight > windowWidth * 0.99) {
hideTimer = setTimeout(() => {
if (!isDragging && !isHidden) {
container.style.transform = `translateX(${windowWidth - playerRight + 180}px)`;
isHidden = true;
}
}, 500); // 延迟500ms缩回,避免误触
}
});
// 3. 鼠标进入iframe区域:禁用拖动,恢复点击播放功能
iframe.addEventListener('mouseenter', function() {
isOverIframe = true;
handle.style.pointerEvents = 'none';
handle.style.cursor = 'pointer';
if (hideTimer) clearTimeout(hideTimer);
});
// 4. 鼠标离开iframe区域:恢复可拖动状态
iframe.addEventListener('mouseleave', function() {
isOverIframe = false;
handle.style.pointerEvents = 'auto';
handle.style.cursor = 'move';
});
// 拖动开始
handle.addEventListener('mousedown', function(e) {
isDragging = true;
offsetX = e.clientX - container.offsetLeft;
offsetY = e.clientY - container.offsetTop;
container.style.transition = 'none';
if (isHidden) {
container.style.transform = 'translateX(0)';
isHidden = false;
}
if (hideTimer) clearTimeout(hideTimer);
});
// 拖动中
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
let x = e.clientX - offsetX;
let y = e.clientY - offsetY;
// 限制在窗口内拖动,避免完全拖出屏幕
x = Math.max(-container.offsetWidth + 30, Math.min(x, window.innerWidth - 30));
y = Math.max(0, Math.min(y, window.innerHeight - container.offsetHeight));
container.style.left = x + 'px';
container.style.bottom = 'auto';
container.style.top = y + 'px';
});
// 拖动结束,自动判断是否隐藏
document.addEventListener('mouseup', function() {
if (!isDragging) return;
isDragging = false;
container.style.transition = 'transform 0.3s ease-in-out';
const playerRight = container.offsetLeft + container.offsetWidth;
const windowWidth = window.innerWidth;
if (playerRight > windowWidth - 10) {
container.style.transform = `translateX(${windowWidth - playerRight + 200}px)`;
isHidden = true;
} else {
container.style.transform = 'translateX(0)';
isHidden = false;
}
});
</script>步骤2:获取并替换自己的歌单ID
打开网易云音乐(网页端/客户端均可),找到需要的歌单;
右键歌单,选择「分享」,复制歌单链接;
链接格式示例:
https://music.163.com/#/playlist?id=12616213453;链接中
id=后面的纯数字,就是歌单ID;按「周日~周六」的顺序,替换代码中
dailyPlaylistIds数组内的数字即可。
步骤3:Halo 后台部署
登录 Halo 博客后台,依次打开:设置 → 代码注入 → 全局 Head 标签;
删除之前的旧版播放器代码;
粘贴修改好的新版完整代码;
点击保存,刷新博客页面即可生效。
五、常见问题排查
问题1:播放器正常显示,但播放卡死,显示 -0:00
歌单为私密歌单,外链无法读取,需改为公开歌单;
歌单内包含 VIP、灰色无版权歌曲,外链无法解析播放;
测试方案:替换官方公开测试歌单 ID
19723756,能播放再更换自定义歌单。
问题2:不会自动换歌单,一直播放同一首
检查7个歌单ID是否全部一致,需配置不同ID才可切换;
核对数组顺序是否为「周日到周六」,顺序错误会导致切换异常;
确认未删除
setDailyPlaylist()初始化代码。
问题3:拖动、贴边隐藏功能失效
未修改播放器容器、手柄的 ID,任意ID修改都会导致交互失效;
代码粘贴不完整,存在缺失、换行错乱问题,建议重新完整粘贴。
六、写在最后
本次升级在保留原有高颜值、高适配交互的基础上,解决了旧版播放器最大的播放兼容问题,新增每日换歌单功能,让博客背景音乐不再单调。全程零代码难度,所有博主均可快速部署。后续会继续持续进行优化