运用js中的单例模式、观察者模式实现弹幕功能

实现的功能:在一个视频中实现发弹幕的功能,通过在文本框中输入将要发布的内容,按下回车键时,这条内容会在视频右边一个随机的高度显示出来,并从视频右边移动至视频左边直至消失。

这个功能的实现主要运用了观察者模式,指多个对象间存在一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。这种模式有时又称作发布-订阅模式、模型-视图模式,它是对象行为型模式。在这个例子中,通过观察者模式来监视对象的行为,当我们按下回车键时,执行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>

实现效果展示:
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值