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

video组件上弹幕不显示?先解决层级问题
绝大多数“弹幕看不见”不是逻辑写错了,而是被 video 压在下面了。uni-app 的 video 是原生组件,iOS 和 Android 都默认置顶,z-index 完全无效——哪怕你设成 99999 也没用。
- 微信小程序必须用
cover-view包裹弹幕容器,或更优的cover-canvas方案;普通view在真机上必然不可见 - App 端优先走
subNVue,别硬扛cover-view;nvue 页面能和video同级渲染,是唯一稳定方案 -
pages.json中subNVue配置漏掉position: "absolute"或zIndex(必须为数字,如100),会导致弹幕错位甚至被状态栏切掉 - 千万别对
video做transform或opacity动画,某些安卓机型会触发覆盖层闪退
canvas 渲染弹幕卡顿?换预计算 + drawImage
非 H5 平台(尤其小程序)的 canvas 不支持 requestAnimationFrame 和 DOM 操作,直接用 fillText 绘制文字,在 iOS 小程序里一开弹幕就掉到 10fps。
- 每条弹幕的起始
x、结束x、生命周期时长必须在入场前就预计算好,避免运行时反复调用measureText - 文字绘制统一用
drawImage(把文字提前绘制成离屏 canvas 贴图),禁用fillText;安卓低端机上后者极易卡顿 - 最大并发弹幕数建议 ≤ 30,超出的直接丢弃;不要堆队列——JS 线程和渲染线程耦合紧,积压会雪崩
- 曲线/抖动轨迹必须查表:提前生成整条
y坐标数组,每帧按索引取值;禁止在draw循环里实时算Math.sin
怎么让弹幕沿斜线或正弦曲线飞过?别用全局路径
B站式弹幕不是所有弹幕走同一条线,而是每条绑定独立的 y(t) 函数。
- 正弦扰动公式:
y = baseY + amplitude <em> Math.sin(2 </em> Math.PI <em> (x / speed) </em> frequency),其中baseY按行号 × 行高算,amplitude控制抖动幅度(通常 2~5px),frequency控制密度(0.5~1.2) - 斜线弹幕用线性方程:
y = k * x + b,k由角度决定(如tan(15°) ≈ 0.268),b要根据入场位置动态偏移,保证起点在屏幕右边界内 - 所有坐标运算必须基于 canvas 像素单位;别混用
rpx——uni.upx2px()只在初始化时调一次,运行时不许出现
点击弹幕没反应?AABB 检测 + 坐标归一化是关键
canvas 是位图,没有 DOM 事件冒泡,touchstart 只能拿到画布区域坐标,无法判断点中哪条。
- 必须维护一份运行时弹幕对象数组,每个含
{id, x, y, width, height, timestamp},且每帧更新其x/y - 触摸时用
canvas.getBoundingClientRect()把屏幕坐标转为 canvas 像素坐标 - 遍历当前存活弹幕,用 AABB 检测:
touchX > item.x && touchX item.y && touchY - 遍历时加 early return:先筛掉
timestamp过期或x + width (已出屏)的弹幕,避免无谓遍历
真正难的不是算法,是跨平台 canvas 的坐标归一、内存回收节奏、以及 subNVue 与主页面之间那层薄薄的通信延迟——这些地方一松懈,卡顿和错位就藏不住。











