Bilibili-Evolved 直播弹幕发送栏组件源码解析:网页全屏下的弹幕输入增强实现

发布时间:2026/9/19 9:49:57
Bilibili-Evolved 直播弹幕发送栏组件源码解析:网页全屏下的弹幕输入增强实现 Bilibili-Evolved 直播弹幕发送栏组件源码解析网页全屏下的弹幕输入增强实现【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved导读本文围绕 Bilibili-Evolved哔哩哔哩增强脚本内置组件「直播弹幕发送栏」展开介绍其在直播网页全屏player-full-win与浏览器全屏模式下于底部控制栏展示弹幕输入框的实现原理并深入剖析组件入口、Vue 组件与样式层的源码细节。读完本文你将掌握该组件从「URL 匹配 → 控制栏挂载 → 原生输入框联动 → 发送回调」的完整调用链理解其如何在不修改 B 站原始 DOM 的前提下完成输入增强。组件是什么该组件位于registry/lib/components/live/danmaku-sendbar/目录其官方描述为在直播的网页全屏和全屏模式状态下在底部显示弹幕栏。即当观众将直播播放器切换为网页全屏或浏览器全屏后原始输入栏被隐藏该组件会在播放器底部控制区注入一个轻量弹幕输入框保持「边看全屏直播边发弹幕」的体验。其组件名为liveDanmakuSendbar显示名称为「直播弹幕发送栏」在设置面板中归属于「直播」live标签分类。目录结构与关键文件文件职责index.ts组件入口负责 URL 匹配、等待控制栏、插入输入框 DOMDanmakuSendbar.vue弹幕输入框 UI 与原生输入框联动逻辑original-elements.tsB 站原始直播页面的 DOM 选择器常量index.md组件描述文档组件入口从 URL 匹配到控制栏挂载1. 登录态校验入口函数首先通过getUID()判断用户是否登录未登录UID 为空则直接返回不做任何注入。这与 B 站弹幕发送需要登录的约束保持一致。2. 直播页面 URL 匹配组件元数据通过urlInclude: liveUrls限定生效范围。在 src/core/utils/urls.ts 中liveUrls定义为export const liveUrls [/^https:\/\/live\.bilibili\.com\/(blanc\/)?[\d]/]即仅当页面 URL 匹配live.bilibili.com/{房间号}可选blanc/前缀用于 web 端与直播姬的区分时组件才运行。3. 等待控制栏出现直播播放器的控制栏是「鼠标移入播放器时创建、移出时销毁」的动态 DOM。因此组件使用waitForControlBar定义于 src/components/live/live-control-bar.ts来监听控制栏容器的子节点变化通过select轮询等待.bilibili-live-player-video-controller或.web-player-controller-wrap容器出现通过childList观察容器子节点变化当.control-area控制栏被创建时执行回调。4. 插入弹幕发送栏在回调中组件先定位控制栏内的.left-area左侧控制器区域选择器定义于 original-elements.ts若找不到则抛出[danmakuSendBar] leftController not found错误。随后通过dq(controlBar, .danmaku-send-bar)检查是否已注入过避免重复插入使用mountVueComponent将 DanmakuSendbar.vue 实例挂载为真实 DOM通过leftController.insertAdjacentElement(afterend, danmakuSendBarElement)将输入框插入到左侧控制器之后与播放器控制栏布局融为一体。5. 卸载与重载组件定义了reload与unload钩子卸载时向document.body添加danmaku-send-bar-unloaded类重载时移除该类。样式层通过该类的有无决定是否显示输入框从而实现「关闭组件后输入框立即隐藏、重新开启后立即恢复」的即时热切换无需刷新页面。弹幕输入框Vue 组件与原生 DOM 的联动DanmakuSendbar.vue 是核心 UI 组件模板极为精简div classdanmaku-send-bar input typetext placeholder发个弹幕呗~ :valuevalue maxlength30 keydown.entersend() inputupdateValue($event.target.value) / /div要点说明maxlength30与 B 站弹幕 30 字上限保持一致回车触发send()发送弹幕输入事件实时同步到原生输入框。与原生弹幕输入框的双向同步组件并不自己发起弹幕请求而是「代理」B 站原始输入框。在mounted钩子中const originalTextArea (await select(originalTextAreaSelector)) as HTMLTextAreaElement const sendButton (await select(sendButtonSelector)) as HTMLButtonElement其中select是 src/core/spin-query.ts 提供的轮询查询工具带超时与最大次数限制用于等待原始弹幕输入框与发送按钮渲染完成。选择器常量如下export const originalTextAreaSelector .control-panel-ctnr .chat-input-ctnr .chat-input export const sendButtonSelector .control-panel-ctnr .chat-input-ctnr ~ .bottom-actions .bl-button--primary即原始输入框位于直播面板的chat-input-ctnr容器内发送按钮为其后的bl-button--primary主按钮。输入同步的三条路径自定义输入 → 原生updateValue(newValue)将值写入originalTextArea.value并通过raiseEvent派发input事件raiseEvent定义于 src/core/utils/index.ts让 B 站自己的输入处理逻辑感知变化。原生 → 自定义监听原生输入框的input与change事件将最新值回填到组件value保证从原始入口如直播面板底部输入框输入时全屏输入框同步显示。属性级拦截兜底当首次挂载时代码重写originalTextArea实例上的value属性 setterObject.defineProperty(originalTextArea, value, { ...original, set(value: string) { original.set?.call(this, value) raiseEvent(originalTextArea, input) }, })这样即使 B 站脚本直接给原生输入框赋值也会自动补发input事件保证同步不遗漏。该操作通过模块级变量changeEventHook保证只执行一次避免重复拦截。发送逻辑send() { if (!this.sendButton.disabled) { this.value this.sendButton.click() } }send()仅在发送按钮可用未禁用时执行先清空自定义输入框再模拟点击原生发送按钮完全复用 B 站原生的弹幕发送链路。组件卸载beforeDestroy时会移除对原生输入框的事件监听避免内存泄漏。样式层全屏模式下的展示控制组件的style部分scss体现了「默认隐藏、全屏展示」的策略.live-web-player-controller { .danmaku-send-bar { display: none; } } .live-web-player-controller { background-image: linear-gradient(to bottom, transparent 20%, rgba(0, 0, 0, 0.9)); }默认情况下输入框隐藏同时为控制栏追加自底部向上渐变至半透明的背景提升底部区域可读性。在media screen and (min-width: 1038px)视口宽度下配合.player-full-win网页全屏与:not(.danmaku-send-bar-unloaded)组件未卸载条件.live-web-player-controller .control-area { .danmaku-send-bar { display: flex; margin: 0 24px; flex: 1 1 0; height: 24px; justify-content: center; align-items: center; input { border: none; border-bottom: 2px solid #fff8; background-color: transparent; color: #fff; flex: 1; max-width: 400px; min-width: 70px; :focus-within { border-color: var(--theme-color); } } } .right-area { flex: 0 0 auto !important; } }样式要点输入框采用「透明背景 白色下划线」的沉浸式设计聚焦时下划线变为主题色var(--theme-color)跟随 Bilibili-Evolved 的主题色系统输入框宽度弹性伸缩flex: 1最大 400px、最小 70px保证窄屏可用.right-area强制flex: 0 0 auto避免右侧控制按钮被挤压变形。与项目的整体关系从更宏观的视角看该组件体现了 Bilibili-Evolved 几个通用设计模式组件元数据驱动通过defineComponentMetadata定义于 src/components/define.ts声明name、displayName、tags、urlInclude、entry、reload、unload等字段统一接入设置面板与生命周期管理。其tags: [componentsTags.live]使用的「直播」标签定义于 src/components/types.ts。不改动原始 DOM 语义通过插入旁路元素 代理原生控件的方式实现增强卸载时可完整还原页面。v1 兼容迁移在 registry/lib/components/utils/v1-migrate/migrate.ts 中存在featureMap(danmakuSendBar, liveDanmakuSendbar, component)映射说明 v1 时代的同名功能在 v2 中更名为liveDanmakuSendbar旧用户导入 v1 设置时可自动迁移到新组件。使用方式在 Bilibili-Evolved 的设置面板中进入「直播」标签分类即可找到「直播弹幕发送栏」将其开启后进入任意直播间并切换为网页全屏或全屏模式底部控制栏即会出现带占位文案「发个弹幕呗~」的输入框回车即可发送弹幕。注意该组件依赖 B 站直播页面的 DOM 结构.control-panel-ctnr .chat-input-ctnr .chat-input等选择器若 B 站改版导致这些结构变化组件会抛出ref elements not found错误并停止工作同时其仅在视口宽度 ≥ 1038px 时展示小窗口下输入框会保持隐藏。【免费下载链接】Bilibili-Evolved强大的哔哩哔哩增强脚本项目地址: https://gitcode.com/gh_mirrors/bi/Bilibili-Evolved创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考