原生JS面向对象式编程实现弹幕,利用观察者模式

直接上源代码
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
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值