我正在参加「兔了个兔」创意投稿大赛,详情请看:「兔了个兔」创意投稿大赛
弹幕功能想必大家都不陌生,今天做一个单人弹幕小游戏,在输入框中输入祝福话语点击发送就能在上面容器中从右到左飘过。
实现
要想实现弹幕功能,我们必须确保以下几个方面:
- 发送的弹幕不能重叠。
- 弹幕之间错行出现。
- 弹幕从右到左的移动。 将以上三个问题解决了我们的弹幕功能也就出来了,剩下的加下细节就可以啦。那么我们开始一个个来实现上述功能,技术栈我用的vue2+elementui,在html页面中引入对应的cdn链接进行开发。
布局
首先画出静态页面,利用flex或者position将容器放到页面中间,如果有需要可以在容器上添加上自己喜欢的背景图:
<!-- 引入vue -->
<script src="https://cdn.jsdelivr.net/npm/vue@2.7.14/dist/vue.js"></script>
<!-- 引入样式 -->
<link
rel="stylesheet"
href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"
/>
<!-- 引入组件库 -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
<div id="app">
<div class="barrage-wrapper" ref="barrageWrapper">
<div class="barrage-main">
<div class="barrage-main-dm" ref="barrageMainDm"></div>
</div>
<el-input v-model="text" clearable placeholder="请输入祝福语" @keyup.enter.native="handleAddContent">
<template slot="append">
<i class="el-icon-position" @click="handleAddContent" ></i>
</template>
</el-input>
</div>
</div>
弹幕数组
为了弹幕之间不重叠,我们利用setInterval让发送的话语间隔出现在屏幕上,这样就有一个问题,如果我们发送的弹幕间隔比较短,上一个弹幕还没出现,现在也发送了,就必须要记住发送过的弹幕,所以我们需要声明一个数组用来保存数据,之所以用数组也是为了后续方便提取数据。
/** 弹幕数组 初始化数据*/
barrages: [ {
content: '恭喜发财'
},
{
content: '兔年大吉'
},
{
content: '新年快乐'
}]
dom池
弹幕可以多行展示,不能只堆积到一行当中,每一行我们也需要设置一个上限,尽量确保每个弹幕都能清楚展示。这里我们在弹幕出现前就创建好小容器,而不是弹幕出现后再创建容器。我们将每一条弹幕当成一个小容器,通过行数与上限数在大容器里面设置好一个个小容器,就像网格一样,创建出来的就是dom池,我们初始化的时候就是再创建dom池。
有了dom池,里面的每个dom我们可以重复利用,提高性能,并且弹幕的移动,可以通过transform:translate加上animation移动每个dom进行实现。
init: function () {
//初始化清空dom池、定时器等
this.domPool = [];
this.barrageMainDm.innerHTML = ``;
clearInterval(this.intervalDM);
// 创建div小容器 双循环一个行 一个列
for (let j = 0; j < 5; j++) {
let doms = [];
for (let i = 0; i < 5; i++) {
let dom = document.createElement('div');
// 设置样式
dom.className = 'barrage-item';
// 根据容器宽度确定每个dom的位置
dom.style.transform = `translate(${this.barMainWidth}px,0)`;
// 设置top确定在那一列
dom.style.top =
j * (this.barrageMainDm.clientHeight / 5) +
'px';
// 动画结束重复利用
dom.addEventListener('animationend', () => {
dom.className = 'barrage-item';
dom.style.transform = `translate(${this.barMainWidth}px,0)`;
dom.style.animation = null;
// 清空自定义样式
this.dmStyles.forEach((key) => {
dom.style[key] = null;
});
if (this.domPool[i][j]) {
this.domPool[i][j].isFree = false;
}
});
doms.push({
row: j,
col: i,
el: dom,
//是否正在用
isUse: false,
//是否空闲
isFree: false
});
}
this.domPool.push(doms);
}
这个就是核心代码,弹幕的移动,添加到空闲的dom当中都是围绕着dom池进行操作的。
播放弹幕
利用上面的dom池我们就可以播放弹幕,首先我们从上面弹幕数组中获取弹幕,利用数组的shift方法获取数组的首个元素,同时我们用watch监听数组长度变化,当数组长度为0就清除定时器:
watch:{
'barrages.length': function (len) {
if (len === 0) {
setTimeout(() => {
this.pauseDm();
}, 8000);
}
}
}
我们输入新语句的时候也通过push方法去添加弹幕,这也是选择数组保存弹幕的原因——方便添加、获取。 下一步我们找到空间的dom将内容添加到dom中,同时添加动画实现移动。
@keyframes barrage-run {
0% {
}
100% {
transform: translate(-100%, 0);
}
}
这样我们弹幕的播放也就实现了。
总结
以上就是弹幕实现的全过程,重点是dom池的创建,后续都是围绕dom池在操作。写下祝福或者心愿让这些出现在弹幕上吧。