弹幕实现 js
弹幕实现的基本原理
弹幕功能的实现主要基于前端技术,通过动态创建DOM元素或Canvas绘制文字,控制其从右向左移动。核心逻辑包括弹幕生成、运动控制、碰撞检测及性能优化。
使用DOM实现弹幕
通过动态创建div元素实现弹幕,适合简单场景:
// 创建弹幕元素
function createDanmu(text, color, fontSize) {
const danmu = document.createElement('div');
danmu.textContent = text;
danmu.style.position = 'absolute';
danmu.style.color = color;
danmu.style.fontSize = `${fontSize}px`;
danmu.style.whiteSpace = 'nowrap';
danmu.style.right = '0';
danmu.style.top = `${Math.random() * 80}%`; // 随机垂直位置
document.body.appendChild(danmu);
return danmu;
}
// 移动弹幕
function moveDanmu(danmu, speed) {
const start = Date.now();
const initialRight = parseInt(danmu.style.right);
const distance = window.innerWidth + danmu.offsetWidth;
function animate() {
const elapsed = Date.now() - start;
const progress = elapsed / (distance / speed);
danmu.style.right = `${initialRight + progress * distance}px`;
if (progress < 1) requestAnimationFrame(animate);
else danmu.remove();
}
requestAnimationFrame(animate);
}
使用Canvas优化性能
对于大量弹幕,Canvas方案性能更优:
const canvas = document.getElementById('danmuCanvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const danmus = [];
class Danmu {
constructor(text, y, speed, color) {
this.text = text;
this.x = canvas.width;
this.y = y;
this.speed = speed;
this.color = color;
}
draw() {
ctx.fillStyle = this.color;
ctx.font = '24px Arial';
ctx.fillText(this.text, this.x, this.y);
}
update() {
this.x -= this.speed;
return this.x + ctx.measureText(this.text).width > 0;
}
}
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
danmus.forEach((danmu, index) => {
danmu.draw();
if (!danmu.update()) danmus.splice(index, 1);
});
requestAnimationFrame(animate);
}
animate();
弹幕轨道管理
避免弹幕重叠可采用轨道系统:
const tracks = Array(5).fill().map(() => ({ y: 0, occupied: false }));
function getAvailableTrack() {
const trackHeight = canvas.height / tracks.length;
for (let i = 0; i < tracks.length; i++) {
if (!tracks[i].occupied) {
tracks[i].occupied = true;
tracks[i].y = i * trackHeight + trackHeight / 2;
setTimeout(() => { tracks[i].occupied = false; }, 2000);
return tracks[i].y;
}
}
return Math.random() * canvas.height; // 无可用轨道时随机位置
}
事件监听与交互
添加发送弹幕功能:
document.getElementById('sendBtn').addEventListener('click', () => {
const text = document.getElementById('input').value;
const color = `hsl(${Math.random() * 360}, 100%, 50%)`;
const y = getAvailableTrack();
danmus.push(new Danmu(text, y, 5, color));
});
响应式处理
窗口大小变化时重置Canvas:
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
});
性能优化建议
- 使用
requestAnimationFrame替代setInterval - 对不可见弹幕进行回收
- 避免频繁DOM操作,优先使用Canvas
- 对弹幕文本长度做限制
- 使用对象池复用弹幕对象







