站里写笔记的时候总想有点背景音乐。网上常见方案是 APlayer + MetingJS 接入网易云/QQ 音乐,但一来依赖外部平台链接不稳定,二来歌单里的歌还可能下架。于是自己手写一个,本地托管 mp3,放在 Blowfish 主题里。
效果 #
右下角悬浮一个播放器卡片:显示当前播放曲目、进度条、上一首/下一首、音量调节。支持折叠,播放时切换页面不中断。
实现步骤 #
1. 创建音乐文件目录 #
在项目根目录下新建 static/music/,把 mp3 文件放进去。Hugo 构建时会原样拷贝到 public/ 下。
site/
├── static/
│ └── music/
│ ├── song1.mp3
│ └── song2.mp32. 编写播放器 Partial #
新建 layouts/partials/music-player.html。播放器只有一个 <div> + 一个 <audio> 标签,配上一段 JS。核心结构:
- 播放列表:一个 JS 数组,每项包含
title和src(相对于static/music/的路径) - 播放控制:
<audio>元素的play()/pause()方法 - 进度条:监听
timeupdate事件,更新<input type="range">的值 - 音量:设置
audio.volume(0-1) - 上一首/下一首:切换
playlist数组索引
const playlist = [
{ title: "Song Name", src: "/music/song1.mp3" },
{ title: "Another Song", src: "/music/song2.mp3" }
];
function loadSong(index) {
audio.src = playlist[index].src;
audio.load();
}
function togglePlay() {
isPlaying ? audio.pause() : audio.play();
}3. 注入到首页 #
编辑 layouts/index.html,在底部加入一行:
{{ partial "music-player.html" . }}如果要全站每个页面都出现播放器,改为加到 layouts/partials/footer.html 或 layouts/_default/baseof.html 中。
4. 样式 #
播放器用 Tailwind 写样式(Blowfish 主题自带 Tailwind v4)。核心:
fixed bottom-4 right-4 z-50→ 固定在右下角rounded-xl shadow-2xl border backdrop-blur→ 毛玻璃卡片效果- 颜色使用
neutral-*和primary-*变量,自动适配明暗主题 <input type="range">用[&::-webkit-slider-thumb]自定义滑块样式
5. 构建 #
hugo构建后 public/ 下会自动包含 music/ 目录中的 mp3 文件和播放器 partial,推送即可。
关键代码解读 #
进度条拖动:监听 <input> 的 oninput 事件,根据滑块百分比计算 audio.currentTime:
function seek(val) {
if (audio.duration) {
audio.currentTime = (val / 100) * audio.duration;
}
}自动播放下一首:监听 ended 事件:
audio.addEventListener("ended", nextSong);折叠/展开:点击顶部横线按钮切换中间两行 div 的 hidden class:
function togglePlayer() {
const inner = player.querySelectorAll("div:nth-child(2), div:nth-child(3)");
inner.forEach(el => el.classList.toggle("hidden"));
}为什么不用 APlayer? #
- APlayer 的网易云歌单依赖外部链接,经常失效
- 引入额外的 JS 和 CSS 依赖
- 样式定制受限于 API
自托管方案只有约 120 行 HTML/CSS/JS,零依赖,完全自主可控。