Skip to content

组件皮肤

主播酱的「组件皮肤」(Skin)让设计师 / 前端开发者用 一段 CSS(可选附带少量结构字段)就能改写内置组件的外观——背景、颜色、描边、阴影、动效乃至重排版式,做出一套套可在画布上一键切换的皮肤。

这与创意工坊两套独立机制

  • 创意工坊挂件:你自带 manifest.json + index.html,在 iframe 里渲染全新的元素
  • 组件皮肤:你不写 DOM,只写 CSS,给主播酱已有的内置组件换皮。组件的 DOM 结构、类名、id 由客户端固定提供,你照着它写选择器即可。

想加一个全新玩法 → 看创意工坊;想给加班机 / 礼物菜单 / 弹幕姬换个好看的样式 → 就在这里。

哪些组件支持皮肤

当前开放皮肤的内置组件有三个(由 config/index.vueSKIN_SUPPORTED_TYPES 决定):

组件元素类型(ElementType包裹层类名皮肤机制
加班机OvertimeMachine.overtime-wrapper作用域注入(data-skin-id
礼物菜单GiftMenu.gift-menu作用域注入(data-skin-id
弹幕姬ChatRendereryt-live-chat-renderer 子树整表主题(<link>,blivechat 风格)

加班机与礼物菜单走同一套作用域注入机制,是最典型的皮肤写法;弹幕姬因为要兼容海量现成的 blivechat 主题,走的是整表主题机制,两者写法不同,分别见各自章节。

工作原理速览

  1. 每个支持皮肤的元素根节点上都有 :data-skin-id="data.skinId"。用户在「样式」面板选了某张皮肤,元素的 skinId 就被写成该皮肤 id。
  2. 皮肤的 CSS 被注入 <style>,并自动作用域.{包裹层类名}[data-skin-id="{皮肤 id}"] 之下。这个前缀的特异性是 (0,3,0),稳定高于组件自身 Vue scoped 样式的 (0,2,0),所以无需 !important 就能覆盖默认外观。
  3. 皮肤还可以带一个 data 字段,里面的键值会被合并进元素数据——用于切换那些决定 DOM 结构的字段(如加班机的 displayMode)。
  4. 内置皮肤打包进客户端(css 字符串);商城皮肤走远端(cssUrl + skinData),应用前由客户端 fetch 下来同样经过作用域处理。

完整机制见 皮肤机制

我想…

想做的事从这里开始
5 分钟做出第一张皮肤(礼物菜单)快速开始
搞清 data-skin-id / 特异性 / CSS 变量 / data 字段到底怎么回事皮肤机制
查礼物菜单的完整 DOM 结构与可用钩子礼物菜单皮肤
查加班机(经典 / 简约两种版式)的 DOM加班机皮肤
给弹幕姬套 / 写一套 blivechat 风格主题弹幕姬主题
把做好的皮肤上架商城上架与分发

关键约定

写任何一张皮肤前,先记住四件事:

  1. 所有规则都包在 .包裹层[data-skin-id="本皮肤 id"] 之下(内置皮肤用 CSS 原生嵌套 + &)。客户端会对没写包裹层的远端皮肤自动补一层,但内置皮肤请按约定手写。
  2. @keyframes 写在顶层(不能放进嵌套块内),名字带皮肤前缀(如 zbj-overtime-classic-aurora-spin)避免多张皮肤全局撞名。
  3. 谨慎改 font-size——它会影响布局尺寸(加班机是 autoSize,会触发重新测高)。皮肤优先改色彩、描边、阴影、背景、装饰。
  4. 背景按需透明——皮肤会叠加在画布上,礼物菜单 / 弹幕姬通常保持透明,只有加班机这类「面板」才需要不透明底板。

术语

术语含义
皮肤(Skin)一段作用于某个内置组件的 CSS(+ 可选 data),见 src/types/skin.ts
包裹层(Wrapper)元素根节点的类名,皮肤选择器的作用域前缀,如 .overtime-wrapper
data-skin-id绑在元素根节点上的属性,值为当前皮肤 id,作用域选择器靠它命中
skinData / data应用皮肤时合并进元素数据的字段(结构性字段,如 displayMode
整表主题弹幕姬专用:一整张 blivechat 样式表,用 <link> 全局加载