实现的功能:在一个视频中实现发弹幕的功能,通过在文本框中输入将要发布的内容,按下回车键时,这条内容会在视频右边一个随机的高度显示出来,并从视频右边移动至视频左边直至消失。
这个功能的实现主要运用了观察者模式,指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。在这个例子中,通过观察者模式来监视对象的行为,当我们按下回车键时,执行add()方法,将input中的内容添加到视频的右方,然后让它到视频左边的距离不断-=speed来向左移动进行更新,直至这个距离小于0时,删除这条内容。
实现步骤:
1、在项目中放入一个视频,我这里放入的视频叫“bind重构.mp4”
2、TimeManager.js
export default class TimeManager{
static _instance;
list=new Set();
ids;
constructor(){
}
static get instance(){
if(!TimeManager._instance){
Object.defineProperty(TimeManager,"_instance",{
value:new TimeManager()
})
}
return TimeManager._instance;
}
add(elem){
this.list.add(elem);
if(this.list.size>0 && !this.ids){
this.ids=setInterval(()=>this.update(),16);
}
}
remove(elem){
this.list.delete(elem);
if(this.list.size===0 && this.ids){
clearInterval(this.ids);
this.ids=undefined;
}
}
update(){
this.list.forEach(item=>{
if(item.update) item.update();
})
}
}
3、Bullet.js
import TimeManager from "./TimeManager.js";
export default class Bullet{
rect;
x;
speed=2;
width;
constructor(txt){
this.elem=this.createElem(txt);
}
createElem(txt){
if(this.elem) return this.elem;
var div=document.createElement("div");
Object.assign(div.style,{
color:"#000000",
whiteSpace:"nowrap",
position:"absolute",
})
div.textContent=txt;
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/3+"px",
left:this.rect.width+"px"
});
this.x=this.rect.width;
this.width=this.elem.offsetWidth;
TimeManager.instance.add(this);
}
update(){
if(!this.width) return;
this.x-=this.speed;
this.elem.style.left=this.x+"px";
if(this.x<-this.width){
TimeManager.instance.remove(this);
this.elem.remove();
this.elem=null;
}
}
}
4、danmu.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: 790px;
height: 40px;
font-size: 30px;
}
.div0{
width: 800px;
height: 800px;
position: relative;
overflow: hidden;
}
</style>
</head>
<body>
<div class="div0">
<video src="./bind重构.mp4" style="height:800px ;width: 800px;" controls></video>
<br>
<input type="text">
</div>
<script type="module">
import Bullet from "./observer/Bullet.js";
var input=document.querySelector("input");
document.addEventListener("keyup",keyHandler);
function keyHandler(e){
if(e.keyCode!==13) return;
if(input.value.trim().length===0) return;
var bullet=new Bullet(input.value);
bullet.appendTo(".div0")
input.value="";
}
</script>
</body>
</html>
实现效果展示: