弹幕盖不住video组件是因为video是原生渲染组件,默认置顶且不参与CSS层叠上下文,z-index无效;iOS/Android真机上即使设z-index为999999也无效;微信小程序须用cover-view或canvas+cover-view组合,App端应优先使用subNVue方案。

弹幕在 uni-app 里根本盖不住 video 组件——不是你代码写错了,是原生组件默认置顶,z-index 完全无效。iOS 和 Android 真机上,哪怕把弹幕层设成 999999,它还是在视频底下。
uni-app 的 video 组件为什么压住所有弹幕
uni-app 的 video 是原生渲染组件,在 App 和小程序端均强制置顶,不参与 CSS 层叠上下文。这意味着:
-
position: absolute+z-index对它完全失效 -
cover-view是微信/支付宝小程序唯一能盖住它的容器(但仅支持基础布局,不能嵌套普通 view) - H5 端可用
div+transform叠加,但 App 端必须换方案 - App 端优先用
subNVue:独立原生窗口,天然高于video,且支持完整 canvas 渲染
canvas 弹幕在非 H5 平台卡顿的真正原因
很多人以为“canvas 就是 canvas”,但在小程序和 App 上,uni.createCanvasContext 不支持高帧率 DOM 动画,requestAnimationFrame 行为受限,直接导致掉帧。
- 别在 draw 循环里调
ctx.fillText():安卓低端机一开就卡,改用ctx.drawImage()预渲染文字贴图 - 每条弹幕的坐标、生命周期必须预计算好,运行时只查表,不实时
measureText - 最大并发数硬限制 ≤ 30 条,超出直接丢弃;堆队列会拖垮 JS 主线程
- 轨迹算法(如正弦抖动)要提前生成整条路径数组,避免每帧算
Math.sin——iOS 小程序性能断崖下跌
点击弹幕怎么精准命中
canvas 是位图,没有 DOM 事件冒泡,touchstart 只能拿到画布坐标,无法自动对应到某条弹幕。
- 先做坐标转换:用
uni.getSystemInfoSync().screenWidth和 canvas 宽高反推 touch 坐标在 canvas 内的位置 - 遍历时加两层过滤:
timestamp (筛旧弹幕)、<code>Math.abs(touchY - item.y) > 10(筛 Y 距离远的) - 命中后异步反馈:
setTimeout(() => { /* 显示气泡 */ }, 0),否则阻塞下一帧绘制 - 检测逻辑必须基于 AABB 碰撞:即
touchX > item.x && touchX item.y && touchY
subNVue 方案为什么是 App 端最优解
App 端不用折腾 cover-view 兼容性或 canvas 性能瓶颈,subNVue 是唯一能同时满足“盖住 video”+“自由 canvas 渲染”+“独立线程”的方案。
- 在
pages.json中为 video 页面声明subNVues,指定一个绝对定位的 nvue 子窗 - 子窗内用
<canvas canvas-id="danmu-canvas"></canvas>,通过uni.postMessage接收弹幕数据 - 子窗背景设为透明:
style.background = "rgba(0,0,0,0)",避免遮挡视频 - 注意 Android 硬件加速问题:需在
manifest.json中开启"hardwareAccelerated": true
最易被忽略的是:所有坐标运算必须统一用像素单位,别混用 rpx;uni.upx2px() 只能在初始化时调一次,运行中反复调会吃性能。真机调试务必关掉开发者工具的“缩放适配”,否则 canvas 坐标全乱。











