anzhiyu 音乐播放器深度魔改系列(三):控制条与布局——展开折叠、音量条与控制台态

开头:移动端布局突然「崩了」

折叠态播放器在手机上打开控制台,封面缩成 25px 小圆点、按钮飞到 120px 外、歌词整个错位——控制台态的音乐布局规则一条都没生效。

排查结论令人震惊:console.css 里大量 .aplayer-withlrc 规则从未匹配过。因为定制版 APlayer 配置是 lrcType: 0,实例 class 只有 aplayer aplayer-withlist,APlayer 只在 lrcType 有效时自动加 withlrc 类——而我们把歌词改成了自绘(见系列第二篇),lrcType 从来没设过。本文从「补类」这个根因讲起,完整梳理控制条与布局的双态体系。

目标声明 + 前置条件

本文带你完成:折叠/展开双态卡片、空闲自动收起、可拖常驻音量条、控制台大圆盘布局,并修好 withlrc 类缺失导致的选择器失效问题。

前置条件:

  • 已完成系列第一、二篇(保活架构 + 自绘歌词)
  • 了解主题 _extra/console/console.css 控制台样式组织

你将学会:

  1. aplayer-withlrc 类缺失的根因与补救
  2. 折叠/展开双态(stretch 类切换)
  3. 自绘常驻音量条(原生弹出条被卡片裁剪)
  4. 控制台态大圆盘布局与移动端适配

Step 1:补上 aplayer-withlrc 类(根因修复)

目的:让 console.css 里依赖 .aplayer-withlrc 的布局规则真正生效。做完这步控制台态布局恢复正常。

操作: 自绘歌词不走 lrcType,APlayer 不会自动加类,JS 手动补上(utils.js:939-940):

1
2
// 控制台打开时的音乐布局规则依赖 .aplayer-withlrc 选择器,主动补上(自绘歌词不走 lrcType,APlayer 不会自动加)
navMusicAplayer.classList.add("aplayer-withlrc");

配套:nav-music 相关 CSS 规则全部改 .aplayer(fix/aplayer.css),音乐馆页 #anMusic-page 保留 withlrc 选择器。

预期输出: 控制台打开后,封面大圆盘、歌词框、按钮定位全部按 console.css 生效。

⚠️ 报错排查(本系列第二大坑):任何「改了 CSS 但页面没反应」的魔改,先怀疑选择器从未匹配——用浏览器 DevTools 的 document.querySelectorAll 验证目标元素实际 class,而不是看 CSS 文件里写了什么。


Step 2:折叠/展开双态(stretch 类)

目的:小卡(41px 胶囊)↔ 大卡(100px + 66px 封面 + 进度条/控制条)双态切换。做完这步点封面/按钮可展开。

操作:

  • JS 切类:musicTelescopic() 切换 stretch 类(utils.js:698-705),展开按钮 _bound 防 pjax 重复绑定(1152-1160),点歌名区也可展开(1163-1167)
  • 折叠态点封面播放按钮真正切换播放/暂停(1168-1173)
  • CSS(fix/aplayer.css):折叠态 41px 高胶囊、播放中金黄底;展开态 100px 高 + 66px 封面 + 右侧信息列 padding: 8px 12px 6px 10px
  • 展开按钮:26px 圆钮、金黄底 #18171d 深字、z-index: 3 防误触顶部返回首页链接、SVG 固定 16px 防变形

预期输出: 点展开按钮卡片放大(按钮 180° 旋转);折叠态点封面播放键可播放/暂停;展开态点返回链接正常。

⚠️ 报错排查:展开按钮要压到卡片上边缘(z-index 提高),否则被封面或返回链接盖住点不到;SVG 不设尺寸会渲染成默认 300px 巨型按钮(本系列实测踩过:歌词开关按钮渲染成 300px)。


Step 3:空闲自动收起 + 自绘音量条

目的:大卡 10 秒无操作自动收回小卡;音量条常驻可拖(原生弹出条被卡片裁剪不可调)。做完这步交互顺手。

操作:

空闲收起(utils.js:751-767):播放中 stretch 态监听 mousemove/click/keydown 刷新计时,10s 无操作自动移除 stretch。

自绘音量条(utils.js:1101-1132):在 .aplayer-time 注入 nav-music-volume-bar:

1
2
// mousedown + document mousemove/mouseup 拖动,volumechange 同步 fill 宽度
// 原生弹出条被卡片裁剪,改为常驻横条

CSS(aplayer.css:504-520):52×4px 横条,填充色主题色;原生弹出条隐藏(477-480)。

预期输出: 展开卡 10s 无操作自动收起;音量条可拖动、音量变化即时反馈。

⚠️ 报错排查:拖动监听挂 document 而非元素(手指移出元素仍能拖);volumechange 同步而不是拖动时才更新,否则键盘/其他路径改音量条不刷新。


Step 4:控制台态大圆盘布局

目的:控制台打开时播放器移入画面中央,封面放大成圆盘、歌词框下移。做完这步控制台音乐区成型。

操作(console.css:327-522 桌面 + 553-982 移动端):

  • 播放器整体居中:桌面 left:45%; top:23%; width:42%; height:35%;移动端 left:5.2%; top:3.9rem; width:85%; height:70%
  • 封面大圆盘:桌面 70px 圆形;移动端 100px + margin-top: 80px
  • #console-music-bg 背景模糊层:scale(1.2) 溢出 + pointer-events: none(否则挡住右上角 widget/关闭按钮点击,本系列踩过)
  • 歌词框:移动端封面下方 25px 高滚动区;控制台态点展开按钮不改变布局(.aplayer-controller 固定 top: 58px)
  • 控制台大按钮:back/forward/play/loop/order/menu 全部 absolute 定位,33% 宽 40px 高
  • 歌词开关按钮:控制台态位于 loop 按钮正下方(top:120px、33%×40px、svg 24px)
  • max-height: 800px 以下隐藏控制台音乐(桌面矮屏适配)

预期输出: 控制台打开后:中央大圆盘封面、歌词在封面下方、六个控制按钮整齐排列、歌词开关在 loop 下方、点任意控件无遮挡。

⚠️ 报错排查:背景模糊层必须 pointer-events: none,否则 scale(1.2) 溢出部分拦截所有点击;控制台态与普通态的布局规则要分开写(#console.show 作用域),避免展开卡影响控制台。


Step 5:深浅色可读性

目的:播放中金黄底全部深色文字,浅色模式白底深色文字。做完这步两种模式都可读。

操作要点(aplayer.css:656-745):

  • 播放提示条金黄底深字:#nav-music-hoverTips { color: #18171d; }
  • 播放中金黄底 → 全部 #18171d:info/歌词当前行/图标/音量条/进度条 rgba(24,23,29,...)
  • 浅色模式:[data-theme="light"] 特例覆盖金黄规则(白底深字)
  • 展开态图标统一 currentColor !important(防 APlayer 默认黑白规则覆盖),浅色再翻深色

预期输出: 播放中/未播放、深色/浅色四种组合下按钮与文字均清晰。

⚠️ 报错排查:currentColor !important 是双刃剑——统一了颜色但也压制主题色区分,图标用 currentColor 文字用固定色,别混用;浅色特例要放在金黄规则之后(CSS 后写者胜)。


检查点:验证整体效果

全部勾选通过 = 控制条与布局达标。

  • 控制台打开布局正常(大圆盘、歌词、按钮齐全)
  • 折叠↔展开切换流畅,按钮无变形
  • 10s 无操作自动收起
  • 音量条可拖、音量即时反馈
  • 深浅色 × 播放/暂停四种组合全部可读
  • 移动端(≤1200px)布局不崩

常见问题(FAQ)

问题 原因 解决
控制台态布局不生效 .aplayer-withlrc 类缺失(lrcType:0) JS 手动 classList.add("aplayer-withlrc")
点不到右上角按钮 背景模糊层拦截 #console-music-bg { pointer-events: none; }
按钮渲染成 300px 巨型 SVG 无 width/height 显式固定尺寸
音量条拖不动 监听挂错元素 拖动监听挂 document
浅色模式看不清 金黄规则覆盖浅色 [data-theme="light"] 特例后置覆盖

总结

控制条与布局篇的核心是「选择器匹配的真相」:CSS 写得再对,元素 class 不对就白写。核心要点:

  1. 先验证 class 再写 CSS:aplayer-withlrc 类缺失是一切布局失效的根因
  2. 双态明确:stretch 类切换折叠/展开,互不干扰
  3. 自绘补短板:原生音量条被裁剪,就自己画一个
  4. 作用域隔离:控制台态规则独立作用域,不污染普通态

延伸阅读: