这个需求如题,大体上是将文章的评论数据,在文章的首图上面以弹幕的形式出现。当时在做这个需求的时候,花了挺多精力的,踩了很多坑,现将弹幕的实现思路写出来,如果喜欢的话可以点波赞/关注,支持一下,希望大家看完本文可以有所收获。
个人博客了解一下:obkoro1.com
实现弹幕的原理,并不算太复杂,耗费一些时间,怼一怼应该都可以做出来。
<div>
<img src="url"/>
<div id="barrageDiv">
<div id="barrageLayer1"></div>
<div id="barrageLayer2"></div>
<div id="barrageLayer3"></div>
<div id="barrageLayer4"></div>
</div>
</div>
<!--detailImg 设置relative, barrageDiv设置z-index在图片上面,以及图片的位置-->
<!---barrageLayer1~4 主要设置了一个top属性让四个div在各自的水平线上,形成四个通道->
关于这里的css样式,关键点都在上面说了,就注意一下上面通道是怎样形成的,就可以了。具体的样式也就不贴出来了,就根据各自的需求来吧。
要实现弹幕效果肯定需要有数据,这里就是发请求了。
获取数据时,要考虑数据量,一次不可能全部都获取,可以一次获取一部分,当数据要加载完的时候,再次请求数据。
这里要记录数据数据是否全部请求完成,如果请求完成,就可以不再发送数据,直接用之前获取的全部数据就可以了。
弹幕数据获取后,就执行弹幕运行的函数,因为我在写弹幕函数的时候,设置了很多数据状态,这里就大概讲一下实现思路和关键部分代码。
移动弹幕的过程中判断四个通道是否处于闲置状态,当dom移动出了屏幕,移动dom并且清除定时器。
function barrage(){
//第一部分先判断数据是否加载完成 这里是一个定时器,设置为15秒。
//如果数据还未加载完毕,就再次运行请求数据的接口,请求的页数可以 数组/每次请求的条数+1
//数据加载完毕就清除定时器。(我将定时器都保存在vue 组件的data里面) 清除的时候clearInterval(this.data);
//定时发射
_this.barrageStatus.divStatus.intervalid=setInterval( selfTime,1100);
function selfTime() {
if(_this.dataNum>=_this.barrageStatus.data.length){
//当dataNum大于等于数组的数量时,弹幕从头再来一遍
_this.dataNum=0;
}
//设置四个通道的变量,当这几个变量为false的时候,才可发射
if(divStatus.div1===false){
//这里只演示其中一个变量
divStatus.div1=true;
_this.dataNum++;
return barrageOut(_this.barrageStatus.data[_this.dataNum-1].content,_this.barrageStatus.data[_this.dataNum-1].commentator.headImgUrl,_this.dataNum);
}
};
// 创建弹幕内容,自定义弹幕移动速度
function barrageOut(text,imgUrl,num) {
//text:弹幕的内容,imgUrl:用户的头像,num:数组的第几个
if(num%4==1){
//根据数组下标 创建对应通道的节点 这里也演示其中一个
barrageLayer=document.getElementById('barrageLayer1');
}
// 创建dom内容 定义dom style样式
let divBox = document.createElement('div');
let divBoxImg=document.createElement('span');
let divBoxText=document.createElement('span');
divBox.setAttribute('class','barrageDivClass');
divBoxText.innerHTML=text;
divBox.appendChild(divBoxImg);
divBoxImg.setAttribute('class','barrageDivClass_img');
divBoxImg.style.backgroundImage=`url(${imgUrl})`;
divBox.appendChild(divBoxText);
divBox.style.left=document.body.clientWidth+2000+'px';// 初始化left位置,一开始在屏幕的右侧
barrageLayer.appendChild(divBox);
// 定时器移动dom,形成弹幕
let time,l=0;
time= setInterval(function(){
if(text.length<15){
// 这里可以根据需求自定义弹幕加载的速度
l=l-1;
}else{
l=l-2;
}
//通过减少left属性移动这个div 从右往左移动
divBox.style.left = document.body.clientWidth+l+'px';
let delDiv=()=>{
if(num%4==1){
//在移动弹幕的过程中判断四个通道是否处于闲置状态 这里只演示其中一个
barrageLayer=document.getElementById('barrageLayer1');
if(barrageLayer.childNodes.length<2){
//判断弹幕数量,如果小于2,设为false,上面的定时器可以继续发射弹幕
divStatus.div1=false;
}else{
divStatus.div1=true;
}
}
}
}
if( l <= (0-divBox.offsetWidth-120) ){
if(_this.barrageStatus.divStatus.switch==true){ //弹幕开关
delDiv();
if(l <= (0-divBox.offsetWidth-document.body.clientWidth) ){
//不断减少left属性,当小于这个内容的宽度,并且滚了120的时候
barrageLayer.removeChild(divBox); //移除dom
clearInterval(time);//清除这个div的定时器
}
}else{
clearInterval(time);//清除这个div的定时器
}
}
},20)
}
}
这个弹幕需求,我是如上这么实现的,回头看看实现,发现还是有不少地方可以优化和拆分的,如果有更好的实现思路和本文有哪些错误,欢迎在评论区下面留言。
首先安装nodejs运行环境, 从 http://nodejs.cn/download/ 下载对应的版本, 安装 huya-danmu 模块, https://github.com/BacooTang/huya-danmu 有详细的安装方法,参照 huya-danmu 模块中 test.js 编写 huya.js 新文件,录视频的同时运行 huyaDanmu 批处理命令, 就不用在调整时间轴;
弹幕是一个很常见的功能,下面是本人封装的一个小小的实现方案,存在不足之处可以提出来或自由改进。直接上代码:效果如图:点击开启弹幕按钮:
经过我多次调试,发现B站的textarea需要触发一个keydown事件之后才能发送。Events 可以使用 Event 构造函数创建如下:请使用 event constructors 来替代.创建一个指定类型的事件。其返回的对象必须先初始化并可以被传递
DPlayer 是一个支持弹幕的 HTML5 视频播放器。支持 Bilibili 视频和 danmaku,支持HLS,FLV,MPEG DASH,WebTorrent以及其他视频格式,支持截屏、热键、切换清晰度以及字幕等。
相信最近有很多B站的用户都注意到了不挡脸的弹幕,打开一则视频右下角的“智能防挡弹幕”功能后,弹幕就不会再覆盖人像,而是呈现从人体身后穿过的效果。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!