ES6利用观察者模式实现发送弹幕

本文介绍了一种基于HTML和JavaScript实现的弹幕发送及动画效果的方法。通过点击按钮或按回车键发送弹幕,利用自定义的Bullet类创建弹幕元素,并通过TimeManager类管理弹幕的动画播放。

通过点击发送按钮或者敲回车实现发送弹幕

HTML文档

bullet.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>
</head>
<style>
    .wrap{
        width: 536px;
        height: 540px;
        position: relative;
        overflow: hidden;
    }
    input{
        width: 460px;
        height: 30px;
        line-height: 30px;
        font-size: 18px;
        border: 1px solid #000000;
        vertical-align: middle;
    }
    button{
        width: 50px;
        height: 30px;
        border: 1px solid #cccccc;
        border-radius: 10px;
        font-size: 16px;
        color: rgb(168, 155, 164);
        float: right;
        
    }
</style>
<body>
    <div class="wrap">
    	<!-- 插入视频 并设置控制面板controls -->
        <video src="./test3.mp4" controls></video>
        <div class="input-wrap">
            <input type="text">
            <button>发送</button>
        </div>
       
    </div>


    <script type="module">
        import Bullet from "./Bullet.js";

        var input=document.querySelector("input");
        var button = document.querySelector("button");

        // 点击发送 或者 敲回车 实现发送弹幕

        // 对 发送按钮 做侦听事件
        button.addEventListener("click",clickHandler);
        // 对 敲回车 做侦听事件
        document.addEventListener("keyup",keyHandler);

        function clickHandler(e){
            if(input.value.trim().length===0) return;
            done();
        }

         function keyHandler(e){
            // 判断是否是回车键
            if(e.keyCode!==13) return;
            if(input.value.trim().length===0) return;
            done();
        }

        function done(){
            // 创建弹幕
            var bullet=new Bullet(input.value);
            // 将弹幕div放入到视频容器中
            bullet.appendTo(".wrap");
            // 发送弹幕后,将每次输入框的内容清空
            input.value="";
        }

    </script>
</body>
</html>

JS文档

Bullet.js

import TimeManager from "./TimeManager.js";


export default class Bullet{
    rect;
    x;
    width;
    // 控制弹幕移动速度
    speed=2;
    constructor(txt){
        // 创建弹幕
        this.elem = this.createElem(txt);
    }

    createElem(txt){
        if(this.elem) return this.elem;
        var div = document.createElement("div");
        Object.assign(div.style,{
            position: "absolute",
            whiteSpace: "nowrap",
            // 设置弹幕文字的颜色
            color : "pink",
            
        })
        // 将输入框的内容传入弹幕中
        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/4+"px",
            left:this.rect.width+"px",
        })
        // 获取当前父容器视口宽度
        this.x = this.rect.width;
        // 获取每条弹幕自身宽度
        this.width = this.elem.offsetWidth;
        // 利用TimeManager 将弹幕放入执行动画的list中  弹幕执行动画
        TimeManager.instance.add(this);
    }

     // 弹幕的动画设置
    update(){
        // 弹幕内容为空时,不执行动画
        if(!this.width) return;
        // 通过改变弹幕距离父容器左边的位置来让弹幕实现从右向左移动的效果
        this.x-=this.speed;
        this.elem.style.left = this.x+"px";
         // 当弹幕完全移出视频容器时,将其从list列表中移除,就停止动画
        // 并且将其弹幕div删除
        if(this.x<-this.width){
            TimeManager.instance.remove(this);
            this.elem.remove();
            this.elem=null;
        }
    }
}

TimeManager.js
这个文件实际上是创建单例并将其放入list中,list是管理动画的列表,通过将弹幕放入到list中来控制是否播放动画。

export default class TimeManager{
    // 创建单例
    static _instance;
    // 将执行动画的项放入list中
    list=new Set();
    // 动画
    ids;

    // 创建构造函数
    constructor(){

    }

    // 创建单例 
    static get instance(){
        if(!TimeManager._instance){
            Object.defineProperty(TimeManager,"_instance",{
                value:new TimeManager()
            })
        }
        // 函数必须要有返回值
        return TimeManager._instance;
    }

    // 添加
    // 将项添加到list中,并根据条件执行动画
    add(elem){
        this.list.add(elem);
        if(this.list.size>0 && !this.ids)
        this.ids = setInterval(()=>this.update(),16);
    }

    // 删除
    // 将项从list中删除,清除动画
    remove(elem){
        this.list.delete(elem);
        if(this.list.size===0 && this.ids){
            clearInterval(this.ids);
            this.ids = undefined;
        }
    }

    // 更新
    // 对list中的每一项执行动画
    update(elem){
        this.list.forEach(item=>{
       		 // 如果该项有update方法时 就执行update方法,就是项对应的动画设置
            if(item.update) item.update();
        })
    }



}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值