本篇简单聊聊前端面试中在react项目中 弹幕 的实现和架构设计
功能
- 弹幕从右侧出现,向左移动,直到完全离开屏幕。
- 通过定时器或requestAnimationFrame更新弹幕位置。
- 弹幕的渲染可以使用DOM元素,也可以使用Canvas绘制。
- 支持不同颜色、样式的弹幕。
- 支持弹幕的暂停、继续、清除。
- 支持弹幕发送。
设计
-
将弹幕功能拆分为几个部分:弹幕数据管理、弹幕渲染、弹幕动画控制。
-
使用Context或Redux管理弹幕数据状态,便于组件间通信。
-
弹幕渲染使用Canvas还是DOM?根据性能需求选择。如果弹幕数量大,使用Canvas性能更好;如果数量不多,使用DOM更灵活。
-
弹幕动画使用CSS3动画或requestAnimationFrame,保证流畅性。
// 弹幕系统架构
class DanmakuSystem {
constructor() {
this.channels = []; // 弹幕轨道
this.pool = []; // 弹幕对象池
this.isPlaying = false; // 播放状态
}
}
// React组件结构
function DanmakuContainer() {
return (
<DanmakuContext.Provider value={danmakuStore}>
<VideoPlayer />
<DanmakuInput />
<DanmakuDisplay />
<DanmakuControl />
</DanmakuContext.Provider>
);
}
代码实现思路
-
弹幕数据通过WebSocket或轮询从服务器获取,然后存储在状态管理中。
-
弹幕组件从状态管理中获取弹幕数据,然后渲染到屏幕上。
-
每个弹幕元素绝对定位,从右侧移动到左侧,移动速度可控制。
-
为了避免重叠,可以采用轨道机制,将屏幕分为多个轨道,弹幕按轨道发射。
// 弹幕核心逻辑
function useDanmaku() {
const [danmakus, setDanmakus] = useState([]);
const containerRef = useRef();
// 添加弹幕
const addDanmaku = useCallback((text, options = {}) => {
const danmaku = {
id: generateId(),
text,
color: options.color || '#fff',
speed: options.speed || 1,
timestamp: Date.now(),
position: calculatePosition() // 计算轨道位置
};
setDanmakus(prev => [...prev, danmaku]);
}, []);
// 弹幕动画
useEffect(() => {
const animate = () => {
setDanmakus(prev =>
prev.map(danmaku => ({
...danmaku,
left: danmaku.left - danmaku.speed
})).filter(danmaku => danmaku.left > -100) // 移除屏幕外的弹幕
);
requestAnimationFrame(animate);
};
animate();
}, []);
return { danmakus, addDanmaku, containerRef };
}
// 弹幕管理系统
class DanmakuManager {
// 1. 轨道管理
allocateChannel(danmaku) {
// 寻找合适的轨道,避免重叠
for (let i = 0; i < this.channelCount; i++) {
if (this.isChannelAvailable(i, danmaku)) {
return i;
}
}
return -1; // 没有可用轨道
}
// 2. 碰撞检测
isChannelAvailable(channel, newDanmaku) {
const existing = this.getChannelDanmakus(channel);
return existing.every(danmaku =>
!this.willCollide(danmaku, newDanmaku)
);
}
// 3. 速度控制
calculateSpeed(danmaku) {
const baseSpeed = 2;
const lengthFactor = danmaku.text.length / 10;
return baseSpeed * (1 + lengthFactor * 0.2);
}
}
总的来说,弹幕功能包含三个主要方面,分别是 数据状态管理、弹幕渲染、弹幕动画控制