弹幕不显示主因是层级问题:video原生组件默认置顶,z-index无效;微信小程序须用cover-view或canvas+cover-view组合,App端应优先使用subNVue方案。

video组件上弹幕不显示?先确认是不是层级问题
绝大多数“弹幕看不见”问题,根本不是代码写错了,而是被视频组件压在下面了。uni-app 的 video 是原生组件,iOS 和 Android 都默认置顶,z-index 对它完全无效——哪怕你给弹幕层设成 99999,也盖不住。
常见错误现象:
• Vue 页面里用 view 写的弹幕,在微信小程序能动,在 App 端直接消失
• cover-view 能显示但文字发虚、动画卡顿、不支持阴影或渐变
• 弹幕位置错乱,比如全堆在左上角,top/left 样式没生效
- 微信小程序必须用
cover-view(或更优的canvas+cover-view组合),不能用普通view - App 端优先走
subNVue,别硬扛cover-view;nvue页面本身就能和video同级渲染 - 千万别在 Vue 页面里对
video做transform或opacity动画——这会触发某些安卓机型的渲染异常,导致覆盖层闪退
微信小程序弹幕卡顿/闪烁?换 canvas 渲染池
cover-view 循环渲染几十条弹幕时,性能会断崖下跌,尤其低端安卓机。官方限制它不支持嵌套、不支持 animation、不支持离屏缓存——这意味着每条弹幕都是实时重绘,帧率很容易掉到 10fps 以下。
实操建议:
• 把所有弹幕文本统一绘制到一个 cover-canvas 上,用 requestAnimationFrame 控制刷新节奏(建议固定 16ms/帧)
• 提前创建 2–3 个弹幕对象池,避免频繁 new/delete 实例
• 弹幕出屏后立即回收坐标和文本引用,防止内存持续增长
关键配置示例:
<video src="xxx.mp4" id="myVideo"></video><cover-view class="danmu-layer"><canvas type="2d" canvas-id="danmuCanvas" style="width:100%;height:100%"></canvas></cover-view>
App端弹幕总被截断或错位?subNVue 配置必须带 position 和 zindex
subNVue 是 App 端唯一靠谱的方案,但它不是“写了就能用”。pages.json 里漏配 position 或 zindex,会导致弹幕层悬浮在错误位置,甚至被状态栏/导航栏切掉。
-
position必须设为"absolute",否则默认是 relative,无法精准对齐视频区域 -
zindex推荐设为100或更高(不要用字符串),部分 Android 原生引擎对数字类型敏感 -
path指向的必须是.nvue文件,不是 .vue;且该文件内不能用px做宽高,得用rpx或 flex 自适应 - 通信靠
uni.$emit/uni.$on,别用vuex或provide/inject——subNVue 和主页面不在同一 Vue 实例树里
弹幕发出去了但收不到?WebSocket 连接没绑定 liveID
前端弹幕“发得出去、收不进来”,90% 是因为没把 WebSocket 实例和当前直播间 ID 绑定死。uni-app 里没有全局单例的弹幕管理器,每个页面都要自己初始化自己的 BarrageState。
典型错误:
• 复用上一个直播页的 liveID,结果新房间收的是旧房间消息
• 在 onUnload 里忘了调用 destroy(),导致多个连接堆积,消息重复或延迟
正确做法:
const { messageList } = useBarrageState(liveID); // liveID 必须来自当前页面参数或接口返回
watch(messageList, (newVal) => {
// 只处理 newVal 中 timestamp > lastRenderTime 的新弹幕
});
// 页面卸载时显式清理
onUnload(() => {
barrageState.destroy(); // 注意:不是 this.$destroy()
});
容易被忽略的一点:Android 端开启透明背景时,若未启用硬件加速,WebSocket 心跳包可能被系统休眠策略掐断。需要在 manifest.json 里手动打开 hardwareAccelerated 开关。










