1. 程式人生 > >純js 實現彈幕效果

純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").onclick=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>