Bilibili-Evolved v1 风格设置面板样式组件解析:从样式覆盖到实现原理
2026/9/19 16:59:09 网站建设 项目流程

Bilibili-Evolved v1 风格设置面板样式组件解析:从样式覆盖到实现原理

【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved

Bilibili-Evolved(哔哩哔哩增强脚本)在向 v2 架构演进的过程中,将设置面板重新设计为圆角卡片与弹出式布局。v1-panel组件的作用,是通过一组全局 SCSS 覆盖规则,让设置面板恢复 v1 时代「全屏停靠、无圆角、侧边栏悬浮」的经典外观。本文将围绕该组件的元数据定义与样式实现,结合设置面板、停靠(dock)等源码,逐段拆解其覆盖逻辑、方向适配机制与动画细节,帮助读者理解样式类组件在脚本内的注册方式与写法。

组件概览:一个纯样式组件

v1-panel在组件目录registry/lib/components/style/v1-panel/下仅由三个文件组成:

  • index.md:组件说明文档,内容为「使用 v1 风格的设置面板样式」;
  • index.ts:组件元数据定义,负责向脚本注册该组件;
  • v1-panel.scss:核心样式实现,约 80 行,全部为对设置面板样式的覆盖规则。

从目录归属看,它位于registry/lib/components/style/(样式类组件)分类下,与dark-modescrollbarplayer-shadow等样式组件并列,属于「通过注入 CSS 改变界面外观」的一类功能,不包含任何业务逻辑或entry运行时代码。

组件元数据:instantStyles 注入机制

组件的注册入口是 index.ts,全文如下:

import { defineComponentMetadata } from '@/components/define' export const component = defineComponentMetadata({ name: 'v1PanelStyle', displayName: 'v1 风格设置面板', tags: [componentsTags.style], entry: none, instantStyles: [ { name: 'v1PanelStyle', style: () => import('./v1-panel.scss'), }, ], })

关键点逐项说明:

  • name: 'v1PanelStyle':组件在脚本内部的唯一标识,也是样式注册名与设置项键名的基础;
  • displayName: 'v1 风格设置面板':设置面板(功能列表)中向用户展示的名称,同时也是搜索匹配的文本来源之一(见下文 SettingsPanel 的搜索逻辑);
  • tags: [componentsTags.style]:将组件归入「样式」标签分组,便于在设置面板中按标签筛选;
  • entry: none:组件没有运行时代码,entry为空,说明它纯粹靠样式生效;
  • instantStyles:声明「即时样式」列表。与按需加载的组件样式不同,instantStyles会在组件启用后立刻注入页面,style: () => import('./v1-panel.scss')采用动态import惰性加载 SCSS 内容,编译后由脚本的样式管理模块负责挂载到文档。

这种「元数据声明 + 惰性加载样式」的写法是 Bilibili-Evolved 样式类组件的标准范式,同类组件(如registry/lib/components/style/scrollbar/index.tsregistry/lib/components/style/player-shadow/index.ts)均遵循同一结构,读者可横向对照。

样式实现逐段拆解

v1-panel.scss的全部规则都挂在.be-settings容器类下。.be-settings正是设置面板入口组件SettingsContainer.vue的根节点类名(见 SettingsContainer.vue),它承载了左侧悬浮的「功能 / 设置」两个圆形图标按钮,以及两个弹出面板(widgets-panel-popupsettings-panel-popup)。

1. 弹窗面板:贴边全屏化

.be-settings { > .be-popup { top: 0 !important; left: 0 !important; body.settings-panel-dock-right & { left: unset !important; right: 0 !important; } transform: translateZ(0) translateY(0) translateX(calc(-101% * var(--direction))) !important; --panel-height: 100vh !important; &.open { transform: translateZ(0) translateY(0) translateX(0) !important; } ...
  • 默认情况下将弹出面板固定到视口左上角top: 0; left: 0),并把--panel-height强制设为100vh,即面板高度撑满整个视口——这是 v1 时代「设置页全屏覆盖」的核心观感;
  • 关闭状态下,面板沿--direction方向平移-101%,恰好完全移出屏幕外侧;translateZ(0)用于强制创建独立渲染层,避免位移过程中出现锯齿或闪烁;
  • 当停靠在右侧(body.settings-panel-dock-right)时,left复位、right: 0,面板改从右边缘贴齐。

其中--direction是停靠方向变量:停靠左侧时为1,停靠右侧时为-1(见 src/components/settings-panel/dock/_left.scss 与 src/components/settings-panel/dock/_right.scss)。所有calc(... * var(--direction))的位移都以此实现「同一套规则、左右镜像」的效果。

> * { border-radius: 0 !important; border-width: 0 1px 0 0 !important; height: var(--panel-height) !important; body.settings-panel-dock-right & { border-width: 0 0 0 1px !important; } }
  • 面板内部子元素(即.settings-panel.widgets-panel)的圆角被清零,边框改为仅保留贴边一侧的 1px 分隔线(左侧停靠保留右边框,右侧停靠保留左边框),高度同步撑满视口;
  • 逐条覆盖均带!important,这是样式组件的必然选择——需要压过脚本自身 SCSS(如SettingsPanel.vue中默认的border-radius: 8px)以及页面既有样式。

2. 侧边栏:悬浮胶囊与旋转动画

> .sidebar > * { width: 52px !important; border-radius: 21px !important; transform: translateX(calc(-13px * var(--direction))) !important; display: flex !important; justify-content: flex-end !important; body.settings-panel-dock-right & { justify-content: flex-start !important; } .be-icon { transition: 0.2s ease-out !important; } &:hover { transform: translateX(calc(8px * var(--direction))) !important; .be-icon { transform: rotate(360deg) !important; } } &.open { transform: translateX(calc(12px * var(--direction))) !important; } }

.sidebarSettingsContainer.vue中承载「功能 / 设置」两个图标的悬浮条。v1 风格将其从默认的圆形小按钮(默认尺寸26px、圆形背景,见 SettingsContainer.vue)改造成:

  • 拉长为胶囊:宽度固定52px、圆角21px,图标通过display: flexjustify-content: flex-end靠外侧对齐;
  • 默认半隐藏:整体向屏幕外平移-13px,只露出约一半,符合 v1 时代侧边栏「贴边收纳」的交互习惯;
  • 悬停滑出:鼠标悬停时平移到+8px露出全貌,同时内部图标rotate(360deg)转满一圈,过渡动画0.2s ease-out
  • 激活态:面板打开(.open)时侧边栏滑到+12px的位置并保持。

3. 组件标签:收尾圆角修正

.settings-panel-popup .component-tags .component-tags-item:last-child { border-radius: 0 !important; }

设置面板左侧的标签栏(ComponentTags.vue渲染的.component-tags)在 v1 全屏贴边的形态下,最后一个标签项的圆角被清零,与全屏无圆角的面板观感保持一致,避免出现「面板直角、标签圆角」的割裂感。

4. 功能面板(widgets-panel):单列流式布局

.widgets-panel { padding: 24px !important; @include no-scrollbar(); &-header { margin-bottom: 36px !important; } .widgets-popup { --columns: 1; --medal-columns: 1; --title-columns: 1; left: 50%; top: calc(100% + 4px) !important; transform-origin: top !important; box-sizing: border-box; max-width: calc(100% + 44px) !important; max-height: unset !important; transform: translateX(calc(-50% * var(--direction))) scale(0.9) !important; display: flex !important; flex-wrap: wrap !important; > * { flex-grow: 1; } &.open { transform: translateX(calc(-50% * var(--direction))) scale(1) !important; } body.settings-panel-dock-right & { left: unset !important; right: 50% !important; } } }

功能面板(WidgetsPanel.vue)承载着「已启用功能」的开关列表,v1 样式对它的调整包括:

  • 面板内边距加大到24px,隐藏滚动条(@include no-scrollbar(),该 mixin 定义于脚本共享样式);
  • 强制各列数为1--columns: 1等),功能项改为单列纵向排布
  • .widgets-popup(功能项分组弹出菜单)以left: 50%水平居中、出现在面板头部下方,未展开时scale(0.9)轻微缩小、展开时恢复scale(1),形成「自上而下放大浮现」的入场动效;
  • 停靠右侧时对称切换为right: 50%定位。

与设置面板源码的联动机制

方向变量从何而来

--direction并非由v1-panel.scss定义,而是由停靠样式在body层面维护。设置面板组件在 src/components/settings-panel/index.ts 中监听「设置面板停靠」选项:

addComponentListener( `${metadata.name}.dockSide`, (value: SettingsPanelDockSide) => { document.body.classList.toggle( 'settings-panel-dock-right', value === SettingsPanelDockSide.Right, ) }, true, )

停靠侧由SettingsPanelDockSide枚举(dock.ts)定义,取值为Left = '左侧'/Right = '右侧'。当选择右侧停靠时,body获得settings-panel-dock-right类,同时 dock/_right.scss 在.be-settings上设置--direction: -1;左侧停靠则由 dock/_left.scss 设置--direction: 1v1-panel.scss中的大量calc(... * var(--direction))正是依赖这层「方向变量」实现了左右镜像的同一套布局,这也解释了为什么样式中会出现大量body.settings-panel-dock-right &嵌套选择器来兜底边界情况。

全屏高度与默认高度的差异

脚本默认的面板高度是--panel-height: calc(100vh - 120px)(见 SettingsContainer.vue),弹出面板垂直居中显示、带 8px 圆角(见 SettingsPanel.vue)。v1-panel.scss正是针对这三点(高度、定位、圆角)逐一覆盖,把它拉回 v1 的全屏贴边形态。因此可以推断:该组件的覆盖目标是 v2 重构后的设置面板 DOM 结构,若未来面板 DOM 结构变化,组件也需要同步适配。

组件启停与样式注入

作为「即时样式」组件,v1PanelStyle启用后由脚本的样式管理模块立即注入v1-panel.scss编译产物,关闭后随即移除,无需刷新页面即可在 v1/v2 两套视觉间切换。该组件与「设置面板停靠」选项相互独立:v1 样式在左、右两种停靠下均能正常工作(通过--directionsettings-panel-dock-right类的组合适配)。

在设置面板中定位与搜索

启用后,用户可在脚本设置面板中通过「样式」标签(tags: [componentsTags.style])筛选到「v1 风格设置面板」这一项。设置面板的搜索逻辑(见 SettingsPanel.vue)会将组件的namedisplayName、标签名称与描述文本拼合后做小写匹配,因此搜索「v1」「面板」等关键词即可命中本组件。此外,ComponentTags.vue渲染的标签栏就是上文样式中被修正圆角的.component-tags区域。

小结

v1-panel是 Bilibili-Evolved 中一个典型的「纯样式覆盖型」组件:通过defineComponentMetadata声明元数据、以instantStyles惰性注入 SCSS,用约 80 行带!important的覆盖规则,将 v2 圆角弹出式设置面板还原为 v1 时代的全屏贴边外观。其实现中利用--direction方向变量与settings-panel-dock-right类实现左右停靠的镜像适配,并通过translateX(calc(... * var(--direction)))配合translateZ(0)完成滑入滑出与旋转动画,为读者理解脚本内样式组件的注册方式、覆盖策略与停靠联动机制提供了完整可参考的范例。若需调整 v1 面板的贴边方向、胶囊宽度或动画时长,直接修改 v1-panel.scss 中的对应规则即可。

【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询