h5实现弹幕
实现弹幕的基本原理
弹幕功能的核心在于动态创建并控制多个文本元素在屏幕上移动。通过HTML5的Canvas或CSS3动画可以实现弹幕效果。Canvas适合高性能需求,CSS3动画实现更简单。
使用CSS3动画实现弹幕
创建弹幕容器和样式:
<div class="danmu-container">
<div class="danmu">这是一条弹幕</div>
</div>
<style>
.danmu-container {
position: relative;
width: 100%;
height: 300px;
overflow: hidden;
background: #000;
}
.danmu {
position: absolute;
color: #fff;
white-space: nowrap;
animation: move 10s linear;
}
@keyframes move {
from { transform: translateX(100%); }
to { transform: translateX(-100%); }
}
</style>
动态添加弹幕的JavaScript:
function addDanmu(text) {
const danmu = document.createElement('div');
danmu.className = 'danmu';
danmu.textContent = text;
danmu.style.top = Math.random() * 100 + '%';
danmu.style.color = `rgb(${Math.random()*255},${Math.random()*255},${Math.random()*255})`;
document.querySelector('.danmu-container').appendChild(danmu);
danmu.addEventListener('animationend', () => {
danmu.remove();
});
}
// 示例调用
addDanmu('新弹幕消息');
使用Canvas实现高性能弹幕
Canvas实现更适合大量弹幕场景:
<canvas id="danmuCanvas" width="800" height="300"></canvas>
<script>
const canvas = document.getElementById('danmuCanvas');
const ctx = canvas.getContext('2d');
const danmus = [];
let lastTime = 0;
class Danmu {
constructor(text) {
this.text = text;
this.x = canvas.width;
this.y = Math.random() * canvas.height;
this.speed = 2 + Math.random() * 3;
this.color = `hsl(${Math.random()*360}, 100%, 50%)`;
}
draw() {
ctx.fillStyle = this.color;
ctx.font = '20px Arial';
ctx.fillText(this.text, this.x, this.y);
}
update() {
this.x -= this.speed;
return this.x + ctx.measureText(this.text).width > 0;
}
}
function addDanmu(text) {
danmus.push(new Danmu(text));
}
function animate(timestamp) {
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (let i = danmus.length - 1; i >= 0; i--) {
danmus[i].draw();
if (!danmus[i].update()) {
danmus.splice(i, 1);
}
}
requestAnimationFrame(animate);
}
animate(0);
addDanmu('Canvas弹幕示例');
</script>
弹幕功能优化建议
设置弹幕轨道避免重叠
const tracks = Array(5).fill().map(() => ({y: 0, endX: 0}));
function getAvailableTrack(textWidth) {
const now = Date.now();
for (let i = 0; i < tracks.length; i++) {
if (tracks[i].endX < now) {
tracks[i] = {
y: i * 30 + 20,
endX: now + textWidth * 10 // 估算显示时间
};
return tracks[i].y;
}
}
return Math.random() * canvas.height;
}
添加弹幕交互功能
canvas.addEventListener('click', (e) => {
const rect = canvas.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
danmus.forEach(danmu => {
const width = ctx.measureText(danmu.text).width;
if (x >= danmu.x && x <= danmu.x + width &&
y >= danmu.y - 20 && y <= danmu.y) {
console.log('点击了弹幕:', danmu.text);
}
});
});
弹幕数据管理
对于大量弹幕,需要实现对象池管理:
class DanmuPool {
constructor() {
this.pool = [];
this.active = [];
}
get(text) {
let danmu = this.pool.pop();
if (!danmu) {
danmu = new Danmu(text);
} else {
danmu.text = text;
danmu.x = canvas.width;
danmu.y = Math.random() * canvas.height;
}
this.active.push(danmu);
return danmu;
}
recycle(danmu) {
const index = this.active.indexOf(danmu);
if (index > -1) {
this.active.splice(index, 1);
this.pool.push(danmu);
}
}
}
以上方案可以根据实际需求选择CSS3或Canvas实现,CSS3方案适合简单场景,Canvas方案性能更好且可控性更强。






