使用模块化和观察者模式实现简单的弹幕效果

本文介绍了一个使用观察者模式实现弹幕展示的示例。通过创建时间管理者和弹幕类,实现了弹幕的添加、更新和删除。当用户按下回车键并输入非空内容时,弹幕会添加到屏幕并开始移动。时间管理者负责定时更新弹幕位置,当弹幕移出屏幕时将其删除。此外,文章还提供了HTML、CSS和JavaScript代码实现弹幕系统的细节。
摘要由CSDN通过智能技术生成

业务逻辑

  • 使用观察者模式来实现弹幕时,被观察者可以有n个,所以将每一个弹幕都作为一个被观察者,根据它不同的状态来进行不同的操作
  • add,remove,update状态
  • 观察keyCode为13时并且输入为非空时,我们进行add添加并且开启定时器不停的更新弹幕状态
  • update时,我们改变弹幕在屏幕中的位置(根据我们的视频窗口来进行定位),观察弹幕宽度为0时我们执行删除定时器和并且删除清空box操作

代码实现


<!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>
    .bullet{
      width: 952px;
      height: 40px;
      font-size: 20px;
      color: pink;
      border: 2px solid #666666;
      position: absolute;
      top: 525px;
    }
    .window{
      width: 960px;
      height: 580px;
      position: relative;
      overflow: hidden;
      margin: 50px auto;
    }

  </style>
</head>

<body>
			//我们先写好html样式
  <div class="window">
    <video src="./video/周杰伦 - 不能说的秘密 (《不能说的秘密》电影插曲).mp4"></video>
    <br>
    <input class="bullet" type="text">
  </div>
  <!-- 每一条弹幕都是属于被观察者 -->


  <script type="module">
    import Bullet from "./observer/Bullet.js";
    var input=document.querySelector(".bullet");
    document.addEventListener("keyup",keyHandler);  //侦听键盘事件

    function keyHandler(e){
      if(e.keyCode!==13||input.value.trim().length===0) return;
      let bullet=new Bullet(input.value);
      bullet.appendTo(".window");
      input.value="";  //清空输入框
    }
  </script>
</body>
</html>

这里我们先写一个时间管理者,管理时间

export default class TimeManager{
  static _instance;
  list=new Set();
  ids;
  //只要被我们添加到list中就会执行update方法
  //删除之后就会移除list后就会停止执行update方法
  static get instance(){   //这里我们写一个单例模式
    if (!TimeManager._instance) {
      Object.defineProperty(TimeManager,"_instance",{
        value:new TimeManager()
      })
    }
    return TimeManager._instance;
  }
  constructor(){

  }

  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=>{
      // console.log(item)
      if(item.update) item.update();
    })
  }
}

这里开始写弹幕的实现逻辑

import TimeManager from "./TimeManager.js";
export default class Bullet{
  rect;
  x;
  speed=2;
  width;
  elem;
  constructor(txt){
    this.elem=this.createElem(txt);
  }
  createElem(txt){   //创建弹幕
    if(this.elem) return this.elem;
    const box=document.createElement("div");
    Object.assign(box.style,{
      whiteSpace: "nowrap",
      position:"absolute",
      color:"#FF33FF"
    })
    box.textContent=txt;
    return box;
  }
  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/2+"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;  //当弹幕宽度不存在时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;
    }
  }
}

 至此我们的简单弹幕效果就实现了,当我们从后端接收到弹幕数据时,就进行数据插入渲染,基本所有的动画运动都可以使用我们的时间管理者,也就是观察者模式,也可以尝试使用AMD来写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MaxLoongLvs

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值