13 July 2026, 01:30 (CST)
2026年07月12日 17:30(东八区 / 北京时间)
热力图色差调整 · 文章页音乐播放器 · 进度条本地 seek 根因
概述
本轮三件事:归档/文章页热力图色阶分离、文章页可选音乐播放器(FLAC/MP3 + LRC)、本地 zola serve 下进度条无法跳转的根因与修复。日常构建流程(zola build / zola serve / ./dev.sh / ./build-site.sh)未改;CI 无需改动。
1. 热力图色差调整
1.1 目标
- 归档页(
/archive/):沿用 GitHub 贡献图 绿色 四档色阶,空格子与 L1 对比清晰。 - 文章页(右上角固定挂件):使用 紫色 四档色阶,与全站 accent 一致,避免与归档页混淆。
1.2 实现
| 场景 | CSS 类 | 文件 |
|---|---|---|
| 归档 | .blog-heatmap--archive | static/css/heatmap.css |
| 文章 | .blog-heatmap--article | 同上 |
色阶变量(浅色模式示例):
| 档位 | 归档(绿) | 文章(紫) |
|---|---|---|
| empty | #ebedf0 | #ebedf0 |
| L1 | #9be9a8 | #e9d5ff |
| L2 | #40c463 | #c084fc |
| L3 | #30a14e | #9333ea |
| L4 | #216e39 | #6b21a8 |
深色模式在 @media (prefers-color-scheme: dark) 下各有一套对应值。
文章页热力图与音乐播放器叠放在 .article-widgets-fixed(templates/article.html),固定于右上角,移动端改到底部右侧。
2. 音乐播放器:设计思路
2.1 产品行为
| 项 | 说明 |
|---|---|
| 启用粒度 | 全站 zola.toml 开关 + 单篇文章 front matter |
| 默认态 | 仅显示大号播放按钮;悬停/聚焦展开元信息、歌词、控制条 |
| 音源 | static/music/ 下 歌手-歌名.flac 或 .mp3,优先 MP3 |
| 歌词 | 同名 .lrc,UTF-8 / GB18030 自动识别;卡拉 OK + 横向滚动 |
| 元数据 | 文件名 歌手-歌名 + LRC [ti:] / [ar:],不用 ID3 标签库 |
| 音量 | 点击循环:25% → 50% → 75% → 100% → 静音;喇叭图标自下而上填充 |
| 进度条 | 细轨道 + 圆点滑块;点击/拖动任意位置跳转 |
| 循环 | 默认关;图标 arrow-clockwise / repeat |
| 多曲 | tracks 多于 1 首时显示随机下一首 |
| Safari | 检测后整组件移除(FLAC / seek 兼容性差) |
2.2 文件结构
zola.toml # [extra.music_player] 全站开关
templates/article.html # .article-widgets-fixed 挂载热力图 + 播放器
templates/partials/music_player.html # 挂件 markup + data-tracks JSON
static/css/music-player.css # 三行布局:meta / lyric / bar
static/js/music-player.js # 播放、LRC、seek、音量、Blob 兜底
static/music/ # 音频与 LRC(构建时原样拷贝到 public/music/)2.3 单篇启用示例
[extra.music_player]
enabled = true
tracks = [
{ file = "庄心妍-繁星点点" },
{ file = "周杰伦-青花瓷" },
]测试文章:content/01Write_blog_CMake/2026-07-12-Libs-Manager/index.md。
2.4 关键代码细节
模板:data-tracks 注入曲目列表;data-base 为 /music(可配 base_url)。
resolveAudio():HEAD 探测,优先 MP3,其次 FLAC。
歌词:parseLrc() 解析时间轴;isMetaLyric() 过滤作词作曲等元信息行;syncLyric() 按 timeupdate 切换行并用 clip-path 做逐字高亮。
进度条:不用 <input type="range">(会被主题全局 range 样式覆盖成粗条+白块)。改为 div 轨道 + --progress-pct CSS 变量 + pointerdown/move/up 计算 clientX 比例后设 audio.currentTime。
音量:VOLUME_LEVELS = [0.25, 0.5, 0.75, 1, 0],clip-path: inset(...) 在喇叭图标上显示填充比例。
3. 本地无法拖动:根因分析
3.1 现象
在本地 zola serve 下,点击或拖动进度条后,播放位置回到 00:00 附近(像「从头重播」),而非跳到指定时间。
3.2 复现数据(Chrome 自动化)
| 环境 | audio.seekable.end | 设 currentTime = 50% 后 |
|---|---|---|
zola serve | 0 | 4.73s → 0.23s |
| 支持 Range 的静态服务 | 255.49(全长) | 正常跳到 118.6s |
3.3 根因
不是进度条 UI 坐标算错,而是 HTML5 音频 seek 依赖 HTTP Accept-Ranges: bytes:
- 浏览器需对音频 URL 发 Range 分段请求 才能建立可 seek 区间;
zola serve不返回Accept-Ranges,curl -H "Range: bytes=0-1023"仍得200而非206;- 此时
audio.seekable为空,设置currentTime无效,位置回到 0 附近。
线上 GitHub Pages 支持 Range,部署后(且 static/music/ 已发布)应能直接拖动,无需播完整首。
3.4 修复方案
| 层级 | 方案 | 说明 |
|---|---|---|
| 播放器 JS | ensureSeekable() Blob 兜底 | 首次点击进度条时 fetch 整首音频为 Blob URL,再 seek;不必播完一整首,但大 FLAC 首次可能需等待下载 |
| 本地可选 | scripts/serve-with-ranges.mjs | 带 byte-range 的静态服务,用于本地立刻验证 seek |
| 日常流程 | 保持 ./dev.sh → zola serve | 不强制改用户习惯 |
| CI / 部署 | 不改 deploy_pages.yml | 仍 ./build-site.sh |
dev.sh 已恢复为:
node scripts/encrypt-content.mjs
exec zola serve "$@"4. 本地 / 部署命令对照
| 场景 | 命令 | 进度条 seek |
|---|---|---|
| 日常预览 | zola build → zola serve | 首次拖可能等 Blob 下载;之后正常 |
| 加密文章开发 | ./dev.sh | 同上 |
| 正式构建 / CI | ./build-site.sh | 构建产物;线上 GitHub Pages 可直接 seek |
| 本地想立刻拖 | 见下方两行 | 与线上一致,无需等 Blob |
本地立刻可 seek(可选,不影响日常):
zola build --base-url http://127.0.0.1:1111/
node scripts/serve-with-ranges.mjs --no-watch -p 1111浏览器打开 http://127.0.0.1:1111/。--base-url 仅修正本地资源链接,seek 能力来自 serve-with-ranges.mjs。
5. 部署注意
- 音乐文件须纳入仓库
static/music/,随./build-site.sh进入public/music/。 - 当前若线上
/music/...为 404,播放器无法加载音频;推送含音乐的构建后即可。 - Workflow 无需修改。
6. 相关文档
- 用法速查已写入 @/03Share_blog/2026-06-22-zola-template-markdown-guide/index.md §8.1 音乐播放器、§8.2 构建命令对照。