JS實現視訊彈幕效果
阿新 • • 發佈:2021-09-13
使用ES6的模組化開發及觀察者模式來實現。觀察者模式有很多種形式,這裡是使用“註冊—通知—撤銷註冊”的形式。TimeManager類可以返回一個單例,每一條彈幕作為一個觀察者,註冊到TimeManager類的單例的set表中,當單例的set中有資料時,被觀察者狀態被改變,執行動畫,並通知所有觀察者進行update狀態更新。彈幕移動超過視訊寬度時,從TimeManager中登出。當TimeManager單例的set表中所有被觀察彈幕都登出時,setInterval停止執行。
1、Bullet.:
觀察者:實現彈幕樣式,和自身狀態更新update()方法.
2、TimeManager.js
被觀察者和Subject:可以增加和刪除觀察者物件,狀態改變時通知所有觀察者並更新狀態。
3、Player.js
播放器元件:簡單的播放器樣式,控制按鈕等都是預設樣式。。。
4、實現效果:
5、具體實現:
import TimeManager from './TimeManager.js'; export default class Bullet{ elem; x; speedX=2; width; constructor(txt){ this.elem = this.createElem(txt); } createElem(txt){ if(this.elem) return let div = document.createElement("div"); Object.assign(div.style,{ position:"absolute",whiteSpace: "nowrap",fontSize:"16px",// color:"#000",color:"#e00",}) div.textContent = txt; return div } appendTo(parent){ if(typeof parent === "string") parent = document.querySelector(parent); parent.appendChild(this.elem); let rect = parent.getBoundingClientRect(); this.elem.style.top = Math.random()*rect.height/4 +"px"; this.width = this.elem.offsetWidth; this.x = rect.width; this.elem.style.left = this.x + "px"; TimeManager.instance.add(this); } update(){ if(!this.elem) return; this.x -= this.speedX; this.elem.style.left = this.x +"px"; if(this.x<-this.width){ this.elem.remove(); TimeManager.instance.remove(this); this.elem = null; } } }
export default class TimeManager{ static _instance; list = new Set(); ids; constructor(){ } static get instance(){ TimeManager._instance = TimeManager._instance? TimeManager._instance : new TimeManager(); return TimeManager._instance; } add(elem){ if(!elem) return if(elem.update) this.list.add(elem); if(!this.ids) this.ids = setInterval(()=>{ this.update(); },16); } remove(elem){ if(!elem) return this.list.delete(elem); if(this.list.size===0 && this.ids){ clearInterval(this.ids); this.ids=0; } } update(){ this.list.forEach(item=>{ item.update(); }) } }
import Bullet from './Bullet.js';
export default class Player extends EventTarget{
static WIDTH=638;
static HEIGHT=493;
elem;
input;
constructor(path){
super();
this.elem = this.createElem(path);
document.addEventListener("keyup",e=>this.keyHandler(e));
}
keyHandler(e){
if(e.keyCode !== 13) return;
if(this.input.value.trim().length===0) return;
let b = new Bullet(this.input.value);
b.appendTo(this.elem);
this.input.value = "";
}
appendTo(parent){
if(typeof parent==="string") parent = document.querySelector(parent);
parent.appendChild(this.elem);
}
createElem(path){
// 播放器最外層容器
let player = document.createElement("div");
player.className = "player";
Object.assign(player.style,{
width:Player.WIDTH+"px",height:Player.HEIGHT+"px",userSelect:"none",overflow: "hidden",position:"relative",verticalAlign:"baseline",})
// 播放器視訊播放部分:應包括頂部作者和反饋欄、視訊狀態按鈕、視訊展示部分。。。。
let videoWrap = document.createElement("div");
Object.assign(videoWrap.style,{
width:"100%",height:"447px",backgroundColor:"#000",top:0,display:"flex",flexDirection:"column",})
// 建立播放器上層:包括標題,作者,反饋意見和舉報等。。。。
let videoTop = document.createElement("div");
Object.assign(videoTop.style,height:"42px",top:"0px",left:"0px",opacity:"0",客棧 color:"#fff",ecBJLH pointerEvents:"none",// transition: "all .2s ease-in-out",transition: "all .2s",})
// 視訊播放狀態開關
// let http://www.cppcns.comvideoState = document.createElement("div");
// 視訊播放部分
let videoContent = document.createElement("div");
Object.assign(videoContent.style,// height:"100%",height:"361px",})
let video = document.createElement("video");
video.src = path;
video.controls = "controls";
video.preload = "auto";
Object.assign(video.style,{
// 視訊居中:進度條被拉長,但是視訊不會被拉長,直接居中:
height:"100%",width:"100%",})
videoContent.appendChild(video);
// 視訊播放和彈幕滾動控制欄:清晰度/倍速/迴圈/映象/寬屏/全屏/進度條等、、、、、
let videoControlWrap = document.createElement("div");
Object.assign(videoControlWrap.style,height:"44px",bottom:"0",})
// 底部發送彈幕及設定傳送彈幕樣式:例如彈幕顏色/字號/滾動/懸停/速度/字型/遮蔽等。。。
let bottomArea = document.createElement("div");
Object.assign(bottomArea.style,height:"46px",})
this.input = document.createElement("input");
Object.assign(this.input.style,{
width:"130px",height:"30px",color:"#212121",// border:"0px",lineHeight:"30px",boxSizing: "border-box",minWidth: "115px",padding:"0 5px",fontSize:"12px",border:"1px solid #e7e7e7",//外框樣式:
backgroundColor:"#f4f4f4",})
bottomArea.appendChild(this.input);
videoWrap.appendChild(videoTop);
videoWrap.appendChild(videoContent);
videoWrap.appendChild(videoControlWrap);
player.appendChild(videoWrap);
player.appendChild(bottomArea);
return player;
}
}
<!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> </style> </head> <body> <script type="module"> import Player from './js/Player.js'; import TimeManager from './js/TimeManager.js'; import Bullet from './js/Bullet.js'; // 播放器使用 let player = new Player("./test3.mp4"); player.appendTo("body"); </script> </body> </html>
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。