纯js 实现弹幕效果

弹幕时近几年新兴的一种技术,接下来我要展示的就是怎么实现类似弹幕的效果。

先贴下效果图:



说是效果,要拿出去用肯定是不行的。

先说一下是怎么样的实现方法。弹幕肯定是出现在屏幕上,所以我们暂时把出现弹幕的窗口称为背景。

弹幕肯定尽量不能重叠在一起,所以我把整个弹幕出现的背景划分为几块,如下图:

1
2
3
4
5

什么意思呢?就是这里有5条弹道,弹幕就是出现在这5条弹道之间的一条。具体划多少条弹道,每条弹道的宽度要看你的背景和你自己的设计了。

好了,弹道有了,怎么创建弹幕呢?这里我们用到了appendChild方法,每个弹幕的内容都是随机的。然后我固定了弹幕的数量,并且加了定时器,

当弹幕到达左边时,弹幕内容再次随机,输入框发送的弹幕出现一次后,将内容加入到预备词库中,并将此弹幕删除。防止弹幕过多报错。

同时每个弹幕出现的时机肯定不能相同,所以我在每个弹幕最开始出现时加了延迟。

大概的设计就是这样了,这里还是总结一下存在的问题:

1.弹幕有时会出现同时出现在同一个弹道上,甚至重叠,暂时还没找到原因。

2.当输入框连续多次发送弹幕时,可能会因为弹道不够出现意外的情况。

3.与真正的弹幕相比,只是简易版的,功能单一。


代码贴上:

<!--作者:natural_live 时间:2017-7-30 -->
<!doctype html>
<html lang="en">
 <head>
  <meta charset="UTF-8">
  <meta name="Generator" content="EditPlus®">
  <meta name="Author" content="natural_live">
  <meta name="Keywords" content="barrage">
  <meta name="Description" content="">
  <title>弹幕</title>
  <style>
	*{margin:0;padding:0;}

	#barrage{
		margin:auto;
		margin-top:50px;
		position:relative;
		width:800px;
		height:400px;
		background:#fff;
		border:2px solid #ffcc00;
	}

	#barrage div{
		width:100%;
		height:20px;
		line-height:20px;
		position:absolute;
	}

	#btn{
		margin:auto;
		margin-top:30px;
		height:50px;
		width:300px;
	}
	#text{
		font-size:20px;
		height:30px;
		border-radius:4px;
		border:1px solid #c8cccf;
		color:#6a6f77;
	}
	#submit{
		padding:7px;
		font-size:14px;
		height:30px;
		border-radius:4px;
		border:1px solid #c8cccf;
	}
  </style>
 </head>
 <body>
	<div id="barrage"></div>
	<div id="btn">
		<input type="text" id="text"></input>
		<input type="button" id="submit" value="发送"></input>
	</div>
	<script>
		var timer=null;
		var current=[];//存储当前输入框的内容
		var newarr=[];//存储每个弹幕距左边框的距离
		var flag=0;//标志量
		var num=new Array();//数组,用来存储划分每个块的序号
		//var t=12;
		var words = ["富强","民主","文明","和谐","自由","平等","公正","法治","爱国","敬业","诚信","友善"];
		function $(id){
			return document.getElementById(id);
		}
		for(var i=0;i<$("barrage").offsetHeight/20 - 1;i++){
			num.splice(i,0,i);//将整个显示框划分成多个块,并对每个块进行标号
			//console.log(num)
		}
		//console.log(num)
		//console.log(num.length)

		window.onload = function(){//加载页面发生的事件

			clearInterval(timer);//清除定时器
			for(var i = 0;i<10;i++){
				setTimeout(function(){
					var word=words[random(0,words.length-1)];//随机产生一个弹幕的内容
					create(word);//创建一个弹幕
				},100*random(10,100))//给弹幕随机加一个延迟
				
			}
			timer=setInterval(move,20);//开启定时器
		}

		function create(w){//创建一个弹幕
				var node=document.createElement("div");//创建一个div元素,用来存储弹幕的信息
				//console.log(words.length)
				node.innerHTML=w;
				//console.log($("barrage").offsetHeight)
				var t= random(0,num.length-1);
				//console.log(num)
				node.style.top=num[t]*20+"px";//从划分的块中随机选中一块。
				Delete(num[t]);//删除已被选中的块
				//console.log(t)
				//console.log(node.style.top);
				node.style.left="800px";
				node.style.color="#"+randomColor();//随机颜色
				$("barrage").appendChild(node);//插入子节点
				flag++;//创建了一个新弹幕时,更新为0
				
				//console.log(node.offsetLeft)
		}

		function move(){
			var arr=$("barrage").getElementsByTagName("div");//获取所有的弹幕
            for(var i=0;i<arr.length;i++){
                newarr.push(arr[i].offsetLeft);//将每个弹幕距左边边框的距离分别存储在newarr数组中
                arr[i].style.left=newarr[i]+"px";//更新距离
                newarr[i] = newarr[i] - 2;//每次减少2px
                if(newarr[i]<0){
					//console.log(arr[i].innerHTML)
					if(currentTest(arr[i].innerHTML) && flag != 0){//当是从输入框发送的弹幕时而且是第一次时,将内容添加到预备的词库中,并删除这个div元素。这么做是为了将弹幕数量维持在一定数量,防止在输入框发送大量弹幕,导致出现错误。
						//console.log(current)
						words.push(arr[i].innerHTML);
						$("barrage").removeChild(arr[i]);
						newarr.splice(i,1);//在newarr中删除这个div
						flag--;
					}else{//当弹幕到达最左边时,弹幕内容再次随机,同时,将这个块加入到预选块中,并在预选块中随机再选一个,颜色也再次随机,这样就保持块的数量不变。
						newarr[i]=800;
						//console.log(parseInt(arr[i].style.top))
						//console.log(arr[i].style.top/20)
						arr[i].innerHTML=words[random(0,words.length-1)];
						num.splice(num.length,0,parseInt(arr[i].style.top)/20);
						
						
						var t= random(0,num.length);
						arr[i].style.top=num[t]*20+"px";
						Delete(num[t]);
						//console.log(num)
						//console.log(node.style.top);
						arr[i].style.left="800px";
						arr[i].style.color="#"+randomColor();
					}
				}
            }
		}

		$("submit").οnclick=function(){//输入款发送弹幕
			create($("text").value);
			current[current.length]=$("text").value;
			//console.log(current)
			$("text").value="";
		}
		//console.log(num)
		function Delete(m){//从预选块中删除已被选择的块
			for(var i = 0;i < num.length;i++){
				if(num[i] == m){
					//console.log(m)
					num.splice(i,1);
				}
			}
		}

		function currentTest(m){
			var fl=false;
			for(var i = 0;i < current.length;i++){
				if(current[i] == m){
					//console.log(m)
					current.splice(i,1);
					fl=true;
				}
			}
			return fl;
		}

		function randomColor(){//随机颜色
			var color=Math.ceil(Math.random()*16777215).toString(16);

			while(color.length < 6){
				color = "0" + color;
			}
			return color;
		}

		function random(m,n){//随机在m、n之间的整数
			return Math.round(Math.random()*(n - m)) + m;
		}
	</script>
 </body>
</html>


  • 10
    点赞
  • 72
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值