前言
- 6000+门店使用的大屏,主机配置竟然是
Android5.5+Chrome 78,不支持es6。。。 - 随随便便一个css动画都可以把页面卡成ppt。
- 开发只给两天。。。
- buff叠满,还想在页面中做
websocket,实现弹幕满屏播放功能。。。
调研尝试了一下,考虑了repaint等因素,用了css的transform:tanslate属性,页面只有两个div在移动页面都卡,无语了,甚至还开启了gpu加速transform:tanslateZ,一样卡成ppt,真的是delay no more了
无奈之下,尝试了自己最不熟悉的Canvas,没想到竟然如此丝滑,把元素调成100个也丝毫不影响性能。
方案有了,下楼买杯瑞幸就是干!!!
大家逛街时估计都见过吧哈哈哈
核心优势
Canvas绘图
- 批量渲染:可以在一次绘制循环中处理所有弹幕,减少浏览器重绘次数。
- 内存效率:不需要为每个弹幕创建DOM元素,降低内存使用。
- 灵活性:可以轻松实现复杂的视觉效果和碰撞检测。
requestAnimationFrame
function animate() {
// 更新弹幕位置
updateBarrages();
// 渲染弹幕
renderBarrages();
// 循环调用
requestAnimationFrame(animate);
}
requestAnimationFrame(animate);
与setTimeout或setInterval相比,requestAnimationFrame有以下优势:
- 与显示器刷新率同步,通常是60fps,减少丢帧。
- 在标签页不可见时自动暂停,节省资源。
- 允许浏览器优化并合并多个动画操作,提高性能。
队列虚拟列表:突破性能瓶颈
为了处理大量弹幕,实现了一个队列虚拟列表:
class CanvasBarrage {
// ...其他代码
handleBarrageRenderList() {
// 移除已经离开屏幕的弹幕
this.barrageList = this.barrageList.filter(item => !item.isExit);
// 添加新的弹幕到渲染列表
let addList = this.handleBarrageOriginList(this.barrageOriginList);
addList = this.handleBarragePosition(addList);
this.barrageList = this.barrageList.concat(addList);
this.barrageCleanCount = 0;
}
}
优势包括:
- 内存优化:只保留屏幕上可见的弹幕对象,大幅减少内存使用。
- 渲染优化:每帧只需要处理有限数量的弹幕,显著提升渲染性能。
- 无限循环:当所有原始弹幕都被使用后,列表会从头开始重新使用,实现无限弹幕效果。
自适应
支持px到vw的转换,使弹幕在不同屏幕尺寸下都能正常显示。
使用介绍
配置参数
以下是CanvasBarrage类的主要配置参数:
| 参数名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
| id | string | null | 容器元素的选择器 |
| barrageList | IBarrageItem[] | [] | 初始弹幕列表 |
| barrageRow | number | 5 | 弹幕行数 |
| barrageSpace | number | 50 | 弹幕间隔 |
| toVw | boolean | false | 是否转换为vw单位 |
| basePx | number | clientWidth | 基准像素值 |
| renderSize | number | 50 | 渲染size |
| fontSize | number | 20 | 字体大小 |
| fontFamily | string | 'Arial' | 字体族 |
| isRandomFontColor | boolean | false | 是否使用随机字体颜色 |
| fontColor | string | 'black' | 字体颜色 |
| barrageSpeed | number | 1 | 弹幕速度 |
| renderOverLimit | number | 20 | 渲染超出限制数量 |
| maxLimit | number | 200 | 最大渲染数量 |
使用方法
const barrageSystem = new CanvasBarrage({
id: '#video-container',
barrageList: initialBarrages,
barrageRow: 10,
fontSize: 24,
isRandomFontColor: true
});
barrageSystem.drawBarrage();
// 添加新弹幕
barrageSystem.addBarrage([{ value: '新弹幕内容' }]);
效果
因为移除了UI,给大家自定义化,所以效果是最原始样式
源码
记得点一个star哦
END
- 大家可以在评论区讨论一下为什么用Canvas渲染会比CSS好
- 希望这篇文章可以帮助到有需要的小伙伴们,有问题可以评论或私信我呀🤞🤞