Bilibili-Evolved 播放器投影(player-shadow)组件详解:为播放器添加主题色投影
【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved
播放器投影(player-shadow)是 Bilibili-Evolved 中一个纯样式型(Style-only)组件,它以播放器主题色为基调,为视频播放器容器添加一圈柔和的同色系投影,并在暗色模式下自动降级透明度,从而让播放器在页面上更具层次感。本文将以该组件的官方文档说明为骨架,结合仓库源码深入讲解其配置、实现原理与定制思路,帮助你理解「主题色投影」这一视觉特效是如何在增强脚本中被定义、注入与生效的。
一、组件定位与官方说明
官方文档对本组件的描述只有一句核心说明:
为播放器添加主题色投影。
这短短一句话定义了组件的全部职责:它不修改任何页面逻辑,只负责为 B 站播放器元素添加一段基于主题色的box-shadow样式。从组件元数据(registry/lib/components/style/player-shadow/index.ts)可以看到它的完整定位:
- 名称:
playerShadow - 显示名称:播放器投影
- 标签:
style(样式类)与video(视频类),归类于样式组件库 - 生效范围:
urlInclude: allVideoUrls,即仅在视频相关页面注入
export const component = defineComponentMetadata({ name: 'playerShadow', displayName: '播放器投影', entry: none, instantStyles: [ { name: 'playerShadow', style: () => import('./player-shadow.scss'), }, ], tags: [componentsTags.style, componentsTags.video], urlInclude: allVideoUrls, })注意entry: none:该组件没有运行时入口函数,纯粹依赖instantStyles(首屏样式)工作。这是 Bilibili-Evolved 中一类典型组件——纯样式组件,通过组件元数据直接声明样式文件,由框架在页面加载早期注入,无需任何 JS 逻辑参与。
二、样式实现:一行 box-shadow 的细节
组件的核心样式位于 registry/lib/components/style/player-shadow/player-shadow.scss:
#bilibili-player, #bilibili-player.mini-player::before { box-shadow: 0px 2px 8px 0px var(--theme-color-30) !important; body.dark & { box-shadow: 0px 2px 8px 0px var(--theme-color-20) !important; } } #bilibili-player-placeholder, .bpx-player-container { box-shadow: none !important; }可以拆解为三层逻辑:
1. 主播放器:主题色投影
#bilibili-player { box-shadow: 0px 2px 8px 0px var(--theme-color-30) !important; }box-shadow: 0px 2px 8px 0px:水平偏移 0、垂直偏移 2px、模糊半径 8px、扩散半径 0,是一个向下轻微偏移的柔和阴影;var(--theme-color-30):使用 CSS 自定义属性(变量),取值为主题色的 30% 透明度版本,从而使投影颜色与用户在设置面板中选择的全局主题色保持一致。
2. 迷你播放器:伪元素投影
#bilibili-player.mini-player::before { box-shadow: 0px 2px 8px 0px var(--theme-color-30) !important; }当播放器进入「迷你播放器」模式时,投影改为作用于#bilibili-player的::before伪元素。这与迷你播放器的实现方式相配合——迷你播放器依赖伪元素绘制自身的容器外观(参见 registry/lib/components/touch/mini-player/mini-player.scss 中对#bilibili-player.mini-player的选择器使用),因此投影也必须跟随伪元素挂载,否则阴影会因容器重构而丢失。
3. 暗色模式:自动降透明度
body.dark & { box-shadow: 0px 2px 8px 0px var(--theme-color-20) !important; }在暗色模式下,投影透明度从--theme-color-30(30%)降为--theme-color-20(20%)。这是因为暗色背景下过强的阴影会显得突兀,降低透明度可让投影更收敛、更自然。body.dark是 Bilibili-Evolved 暗色模式在body元素上统一添加的标记类。
4. 排除占位元素:避免阴影叠加
#bilibili-player-placeholder, .bpx-player-container { box-shadow: none !important; }播放器在加载前存在占位元素(#bilibili-player-placeholder),新版播放器还有bpx-player-container容器。这段规则显式将这些容器的阴影清空,确保投影只出现在最终的播放器本体上,不会因占位层或容器层自带阴影而出现双重投影。
三、主题色变量的底层来源
--theme-color-30与--theme-color-20并非 B 站原生变量,而是由 Bilibili-Evolved 的主题色系统注入的。在 src/core/theme-color/index.ts 的handleThemeColorChange中可以看到变量的生成逻辑:
const handleThemeColorChange = (value: string) => { set('--theme-color', value) for (let delta = 10; delta <= 90; delta += 10) { const color = Color(value, 'hex') set( `--theme-color-${delta}`, color .alpha(delta / 100) .rgb() .string(), ) set(`--theme-color-lightness-${delta}`, color.lightness(delta).rgb().toString()) } // ... }也就是说:
- 用户每设置一个主题色(如
#FB7198),框架会基于该颜色自动生成--theme-color-10至--theme-color-90共 9 个按透明度递减的版本(--theme-color-N即主题色 N% 透明度); - 播放器投影组件直接引用
--theme-color-30/--theme-color-20,因此无需写死任何颜色值,投影颜色会随用户在设置面板中切换主题色实时联动; - 变量最终以
<style>标签注入html根元素,供全页面(含 Shadow DOM 外的主文档)统一消费。
这解释了为什么该组件如此轻量:它只负责「消费」框架已定义好的 CSS 变量,所有颜色计算与联动逻辑都由主题色系统集中完成。
四、instantStyles:首屏样式注入机制
组件元数据中声明的instantStyles字段,是 Bilibili-Evolved 组件框架提供的「首屏样式」注入能力。其类型定义见 src/components/types.ts:
export interface InstantStyleDefinition { /** 样式ID */ name: string /** 样式内容, 可以是一个导入样式的函数 */ style: string | (() => Promise<{ default: string }>) } export interface DomInstantStyleDefinition extends InstantStyleDefinition { /** 设为 `true` 则注入到 `document.body` 末尾, 否则注入到 `document.head` 末尾 */ important?: boolean }结合 src/core/style.ts 的实现可以看到:
instantStyles会在组件启用后尽快注入(早于 DOMContentLoaded),避免出现「样式闪烁」;- 支持函数式懒加载(
() => import('./player-shadow.scss')),样式文件按需打包与加载,未启用该组件时不会引入额外样式体积; - 组件被卸载时,框架会通过
removeInstantStyle等机制移除对应样式的注入,做到启用/停用零残留。
因此,播放器投影组件虽然功能简单,但其「声明式样式 + 首屏注入 + 按需卸载」的生命周期管理完全由组件框架统一承担,开发者只需写一段 SCSS 并声明即可。
五、生效范围与适用前提
组件通过urlInclude: allVideoUrls限定生效范围。allVideoUrls定义于 src/core/utils/urls.ts:
export const allVideoUrls = [...videoAndBangumiUrls, ...cheeseUrls]它聚合了普通视频页、番剧/影视(bangumi)页与课堂(cheese)页三类 URL 规则。也就是说,该组件的投影效果覆盖了 B 站所有带播放器的视频场景——普通投稿视频、番剧、电影、纪录片以及付费课程页面,而在首页、动态、个人空间等非视频页面则完全不会注入。
需要说明的适用前提:
- 该组件只作用于 B 站官方播放器元素(
#bilibili-player及其容器),不作用于页面其他元素; - 效果依赖全局主题色设置:若主题色被重置为默认值,投影颜色会跟随默认主题色变化;
- 纯 CSS 实现,无需任何网络请求与额外权限。
六、如何查看与定制效果
在脚本内启用/停用
安装 Bilibili-Evolved 后,在设置面板的「样式」分类下找到「播放器投影」组件,可自由开关。由于该组件是纯样式组件,开关即时生效,无需刷新页面即可看到投影出现/消失。
手动验证底层变量
如需在浏览器控制台验证投影颜色的来源,可直接查看html根元素的样式:
getComputedStyle(document.documentElement).getPropertyValue('--theme-color-30')修改设置面板中的主题色后,该值会实时更新,播放器投影颜色也随之变化——这是理解「主题色投影」最直观的验证方式。
二次定制思路(参考源码自行实现)
若想调整投影的强度、模糊半径或方向,可参考本文第二节的选择器与变量,自定义一段样式覆盖即可,例如:
#bilibili-player { box-shadow: 0px 4px 16px 2px var(--theme-color-40) !important; }但需注意:Bilibili-Evolved 仓库为只读镜像,不建议(也无法)直接修改组件源码;更合适的做法是通过脚本自身的自定义样式功能注入覆盖样式。
七、小结
播放器投影(player-shadow)组件虽然文档只有一句话、样式只有十余行,但完整展示了 Bilibili-Evolved 组件体系中「纯样式组件」的典型范式:
- 声明式注册:通过
defineComponentMetadata声明名称、标签、生效 URL 与首屏样式; - 零运行时逻辑:
entry: none,样式即组件本体; - 与主题色系统联动:消费
--theme-color-N透明度变量,实现主题色自动同步与暗色模式降级; - 框架化管理生命周期:
instantStyles首屏注入、按需加载、卸载时自动移除。
对于希望理解 Bilibili-Evolved 样式组件编写方式、或想借鉴「主题色变量 + box-shadow」做播放器视觉定制的开发者,本组件是一个小而完整的参考范本。
【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考