弹幕在视频播放时怎么做到不重叠还流畅滚动?
我正在做一个带弹幕功能的视频播放页,现在弹幕是用绝对定位从右往左移动的。但弹道(就是同一时间出现的弹幕行)经常互相覆盖,尤其是高密度的时候,看着特别乱。
我试过给每条弹幕动态计算 top 值避开已有弹幕,但性能很差,一卡一卡的。有没有什么高效又不重叠的实现思路?比如是不是该用 Canvas 或者 CSS 动画优化?
现在的关键代码大概是这样:
function createDanmaku(text) {
const el = document.createElement('div');
el.textContent = text;
el.style.position = 'absolute';
el.style.top = findAvailableTrack() + 'px'; // 这个函数遍历现有弹幕找空位
el.style.left = '100%';
container.appendChild(el);
// 然后用 transition 实现移动
setTimeout(() => el.style.transform = <code>translateX(-${container.offsetWidth}px)</code>, 0);
}
findAvailableTrack这种实时计算太吃性能。建议改用Canvas方案,性能能提升一个量级。核心思路是:
1. 预定义几条弹道(比如5-8条),固定y坐标
2. 每条弹道维护一个队列,记录当前是否有弹幕在占用
3. 新弹幕选择可用弹道,而不是实时计算位置
给你个简化版实现:
优化点:
1. 用requestAnimationFrame代替CSS动画,更流畅
2. 避免频繁DOM操作,Canvas只重绘变化部分
3. 弹道状态管理简单高效,不用实时计算
如果弹幕量特别大,还可以考虑WebGL方案。不过Canvas对大多数场景已经够用了,我去年用类似方案做到同时2000条弹幕不卡顿。