直接上源代码
html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
input{
width: 440px;
height: 40px;
font-size: 30px;
}
button{
width: 80px;
height: 46px;
position: relative;
top: -5px;
outline: none;
}
.div0{
width:536px;
height: 540px;
position: relative;
overflow: hidden;
}
</style>
</head>
<body>
<div class="div0">
<video src="./test3.mp4" controls></video>
<br>
<input type="text">
<button>发送</button>
</div>
<script type="module">
import Barrage from "./js/Barrage.js";
var input=document.querySelector("input");
var button=document.querySelector("button");
document.addEventListener("keyup",keyHandler);
button.addEventListener("click",keyHandler);
function keyHandler(e){
// console.log(e.type);
if(e.keyCode == 13 || e.type==="click") {
if(input.value.trim().length===0) return;
var barrage=new Barrage(input.value);// 将文本内容作为参数带入
barrage.appendTo(".div0");
input.value="";
}
return;
}
</script>
</body>
</html>
JS文件1
export default class Manager{ // 创建单例Manager用来存储数据,并控制交互效果的启动,全靠另外一个类创建实例化对象
static _instance;
list=new Set();
ids;
constructor(){
}
static get instance(){
if(!Manager._instance){
Object.defineProperty(Manager,"_instance",{
value:new Manager()
})
}
return Manager._instance;
}
add(elem){
this.list.add(elem); // 将创建好的元素添加至Set中
if(this.list.size>0 && !this.ids) // 当Set中有元素并且ids没有值时,生成定时器并执行updata函数
this.ids=setInterval(()=>this.update(),16);
}
remove(elem){
this.list.delete(elem);
if(this.list.size===0 && this.ids){ //判断Set中没有元素时,清空定时器
clearInterval(this.ids);
this.ids=0;
}
}
update(){
this.list.forEach(item=>{
if(item.update) item.update();// 判断每个元素是否有updata方法,有该方法才执行
})
}
}
js文件2
import Manager from "./Manager.js";
export default class Barrage{ // 只用来创建实例化对象,不用管创建出来的对象如何存储
rect;
x;
speed=2;
width;
color=this.getRandomColor();// 给弹幕添加随机颜色和边框
constructor(text){
this.elem=this.createElem(text);
}
createElem(text){
if(this.elem) return this.elem;
var div=document.createElement("div");
Object.assign(div.style,{
whiteSpace: "nowrap",
position:"absolute",
color:this.color,
border:"1px solid "+this.color,
padding:"5px",
})
div.textContent=text;
return div;
}
appendTo(parent){
if(typeof parent==="string") parent=document.querySelector(parent);
parent.appendChild(this.elem);
this.rect=parent.getBoundingClientRect();// 获取父元素矩形宽度
Object.assign(this.elem.style,{
top:Math.random()*this.rect.height/4+"px",
left:this.rect.width+"px"
});
this.x=this.rect.width;// 获取父元素宽度,控制弹幕的初始位置以及清除位置
this.width=this.elem.offsetWidth;// 获取元素宽度
Manager.instance.add(this); // 将生成好的元素添加至单例Manager中,并开启定时器
}
update(){ // 控制弹幕移动
if(!this.width) return;
this.x-=this.speed;
this.elem.style.left=this.x+"px";
if(this.x<-this.width){
Manager.instance.remove(this);// 从Manager的Set中删除该元素
this.elem.remove();// 删除该元素
this.elem=null;// 切断引用关系
}
}
getRandomColor(a, r, g, b) {
var col = "rgba(";
for (var i = 0; i < 4; i++) {
if (i < 3) col += ((arguments[i + 1] === undefined ? Math.floor(Math.random() * 256) : arguments[i + 1]) + ",");
else col += ((a === undefined ? Math.random().toFixed(2) : a) + ")");
}
return col
}
}