JS實(shí)現(xiàn)視頻彈幕效果
使用ES6的模塊化開發(fā)及觀察者模式來(lái)實(shí)現(xiàn)。觀察者模式有很多種形式,這里是使用“注冊(cè)—通知—撤銷注冊(cè)”的形式。TimeManager類可以返回一個(gè)單例,每一條彈幕作為一個(gè)觀察者,注冊(cè)到TimeManager類的單例的set表中,當(dāng)單例的set中有數(shù)據(jù)時(shí),被觀察者狀態(tài)被改變,執(zhí)行動(dòng)畫,并通知所有觀察者進(jìn)行update狀態(tài)更新。彈幕移動(dòng)超過(guò)視頻寬度時(shí),從TimeManager中注銷。當(dāng)TimeManager單例的set表中所有被觀察彈幕都注銷時(shí),setInterval停止執(zhí)行。
1、Bullet.js:
觀察者:實(shí)現(xiàn)彈幕樣式,和自身狀態(tài)更新update()方法.
2、TimeManager.js
被觀察者和Subject:可以增加和刪除觀察者對(duì)象,狀態(tài)改變時(shí)通知所有觀察者并更新狀態(tài)。
3、Player.js
播放器組件:簡(jiǎn)單的播放器樣式,控制按鈕等都是默認(rèn)樣式。。。
4、實(shí)現(xiàn)效果:

5、具體實(shí)現(xiàn):
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",
})
// 播放器視頻播放部分:應(yīng)包括頂部作者和反饋欄、視頻狀態(tài)按鈕、視頻展示部分。。。。
let videoWrap = document.createElement("div");
Object.assign(videoWrap.style,{
width:"100%",
height:"447px",
backgroundColor:"#000",
position:"relative",
top:0,
display:"flex",
flexDirection:"column",
})
// 創(chuàng)建播放器上層:包括標(biāo)題,作者,反饋意見和舉報(bào)等。。。。
let videoTop = document.createElement("div");
Object.assign(videoTop.style,{
width:"100%",
height:"42px",
position:"relative",
top:"0px",
left:"0px",
opacity:"0",
color:"#fff",
pointerEvents:"none",
// transition: "all .2s ease-in-out",
transition: "all .2s",
})
// 視頻播放狀態(tài)開關(guān)
// let videoState = document.createElement("div");
// 視頻播放部分
let videoContent = document.createElement("div");
Object.assign(videoContent.style,{
width:"100%",
// height:"100%",
height:"361px",
position:"relative",
userSelect:"none",
})
let video = document.createElement("video");
video.src = path;
video.controls = "controls";
video.preload = "auto";
Object.assign(video.style,{
// 視頻居中:進(jìn)度條被拉長(zhǎng),但是視頻不會(huì)被拉長(zhǎng),直接居中:
height:"100%",
width:"100%",
})
videoContent.appendChild(video);
// 視頻播放和彈幕滾動(dòng)控制欄:清晰度/倍速/循環(huán)/鏡像/寬屏/網(wǎng)頁(yè)全屏/進(jìn)度條等、、、、、
let videoControlWrap = document.createElement("div");
Object.assign(videoControlWrap.style,{
width:"100%",
height:"44px",
opacity:"0",
position:"relative",
bottom:"0",
})
// 底部發(fā)送彈幕及設(shè)置發(fā)送彈幕樣式:例如彈幕顏色/字號(hào)/滾動(dòng)/懸停/速度/字體/屏蔽等。。。
let bottomArea = document.createElement("div");
Object.assign(bottomArea.style,{
width:"100%",
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>
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 簡(jiǎn)單實(shí)現(xiàn)JavaScript彈幕效果
- 基于JavaScript實(shí)現(xiàn)彈幕特效
- JS實(shí)現(xiàn)的視頻彈幕效果示例
- JavaScript直播評(píng)論發(fā)彈幕切圖功能點(diǎn)集合效果代碼
- 一篇文章教你學(xué)會(huì)js實(shí)現(xiàn)彈幕效果
- javascript實(shí)現(xiàn)視頻彈幕效果(兩個(gè)版本)
- javascript實(shí)現(xiàn)彈幕墻效果
- js實(shí)現(xiàn)簡(jiǎn)易彈幕系統(tǒng)
- 原生js實(shí)現(xiàn)彈幕效果
- JS實(shí)現(xiàn)彈幕小案例
相關(guān)文章
JavaScript Date對(duì)象功能與用法學(xué)習(xí)記錄
這篇文章主要介紹了JavaScript Date對(duì)象功能與用法,結(jié)合實(shí)例形式總結(jié)分析了JavaScript Date對(duì)象基本功能、用法及操作注意事項(xiàng),需要的朋友可以參考下2020-04-04
JavaScript實(shí)例--創(chuàng)建一個(gè)歡迎cookie
這篇文章主要介紹了JavaScript實(shí)例--創(chuàng)建一個(gè)歡迎cookie,2022-01-01
JavaScript實(shí)現(xiàn)數(shù)組元素增減的方法示例
數(shù)組元素的增刪是JavaScript的一個(gè)特點(diǎn),因?yàn)槠渌芏嗑幊陶Z(yǔ)言的數(shù)組是不允許增加或者刪除元素的,本文給大家介紹了JavaScript實(shí)現(xiàn)數(shù)組元素增減的方法示例,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下2024-07-07
Javascript中document.referrer隱藏來(lái)源的方法
這篇文章主要介紹了Javascript中document.referrer隱藏來(lái)源的方法,文中通過(guò)一個(gè)實(shí)例給大家介紹了實(shí)現(xiàn)的方法,有需要的朋友可以參考借鑒,下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2017-01-01
淺談JavaScript中的對(duì)象及Promise對(duì)象的實(shí)現(xiàn)
這篇文章主要介紹了淺談JavaScript中的對(duì)象及Promise對(duì)象的實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2015-11-11

