1.需求
在某个位置上展示一些弹幕,弹幕的样式需求如下:![在这里插入图片描述](https://img-blog.csdnimg.cn/20210312173916879.png
2.实现过程
因为在很多位置都需要用到该样式的弹幕功能,所以我将弹幕封装成一个组件(BaberrageVertical),在父组件中传入数据源来进行弹幕数据的显示。
2.1 HTML
2.2.1 父组件
<BaberrageVertical :customers="barrageList" class="helper-top-barrage"/>
Tip:我们可以在此处对弹幕于父组件页面位置进行决定
2.2.2 子组件
<div class="baberradeVertical">
<ul class="baberradeVertical-left">
<li class="baberradeVertical-left-item" v-for="(item,index) in threeObj" :key="index">
<span class="baberradeVertical-left-item-name">{{ item.name }} 是一条</span>
<span class="baberradeVertical-left-item-coursesName">弹幕</span>
</li>
</ul>
</div>
2.2 JS
<script>
export default {
props: {
customers: { // 接收参数,主要为弹幕显示的内容
type: Array,
}
},
data() {
return {
baberrageTimer: null, // 定时器,固定时间内将数据进行操作
threeObj: [], // 过多dom操作影响页面性能,所以用这个来固定几个dom,只修改数据即可
showBaberrageAll: [], // 弹幕池
}
},
methods: {
// 设置弹幕内容
setOperateItem() {
let i = 0;
this.baberrageTimer = setInterval(() => {
// 每一秒,向弹幕池中增加一条数据
this.showBaberrageAll.push(this.customers[i]);
// dom<5 向屏幕中增加数据即可
this.threeObj = this.showBaberrageAll
// 若dom数量过大,将列表中第一个li移除掉,增加一个新的li,这样不会因为循环对动画效果造成影响
if (this.showBaberrageAll.length > 5) {
// 移除第一个dom
const baberrageParent = document.querySelector('.baberradeVertical-left')
baberrageParent.removeChild(baberrageParent.childNodes[0])
// 在列表结尾处新增一个li,用于存放新的元素
let newLi = document.createElement('li')
newLi.className = "baberradeVertical-left-item"
newLi.innerHTML = `
<span class="baberradeVertical-left-item-name">${this.threeObj[4].name} 报名了</span>
<span class="baberradeVertical-left-item-coursesName">${this.threeObj[4].coursesName}</span>
`
baberrageParent.appendChild(newLi)
// 超过五条后,令弹幕池中永远保持同样的数据即可,数量虽然未变,但是内容可以不断更新
this.threeObj.shift();
}
i++;
if (i > 9) {
i = 0;
}
}, 1000)
},
},
// 在页面销毁时清除定时器,否则会影响性能
beforeDestroy() {
clearInterval(this.baberrageTimer)
},
mounted() {
this.setOperateItem();
}
}
</script>
2.3 CSS
这个样式我单独封装成一个less文件,因为在js中有动态增加li及相关样式,若在组件中定义,会因为时机的问题加载不出来
.baberradeVertical-left-item {
background: #666666;
padding: 4px;
display: block;
border-radius: 4px;
animation: slidein linear 5s infinite;
&-name {
color: #FFFFFF;
font-size: 12px;
}
&-coursesName {
color: cadetblue;
font-size: 12px;
line-height: 17px;
margin-left: 4px;
}
}
@keyframes slidein {
0% {
transform: translateX(0, 0);
opacity: 0;
}
20% {
transform: translate(16px, 0px);
opacity: 1;
}
40% {
transform: translate(16px, -20px);
opacity: 1;
}
60% {
transform: translate(16px, -40px);
opacity: 1;
}
80% {
transform: translate(16px, -60px);
opacity: 1;
}
100% {
transform: translate(16px, -80px);
opacity: 0;
}
}
3.遇到问题
在实现结果后会出现如下的问题,当我们在页面停留观看弹幕效果时,如果离开该窗口查看其它内容,计时器和动画效果同步,再次回来时会看到动画效果堆叠在一起,影响体验,解决方法如下:
3.1 方法一:清空所有弹幕内容,重新开始
在页面挂载时,增加一个visibilitychange事件监听器,监听是否在当前页面,如果离开该页面则清空定时器,回来时重新开始定时器,代码如下:
eg:
async mounted() {
// 进入页面时,调用定时器,动画动起来
await this.setOperateItem();
// 加入事件监听器,当离开/回到当前窗口时进行不同的操作
window.addEventListener("visibilitychange", async () => {
if (document.hidden === true) {
// 页面被挂起
clearInterval(this.baberrageTimer);
this.threeObj = [];
this.showBaberrageAll = [];
document.querySelector('.baberradeVertical-left').innerHTML = '';
} else {
// 页面由挂起被激活,弹幕重新开始
await this.setOperateItem();
}
});
}
完全原创哦,转载商用请加水印~
一直在路上,一路不迷茫!