JS實現(xiàn)視頻彈幕效果
使用ES6的模塊化開發(fā)及觀察者模式來實現(xiàn)。觀察者模式有很多種形式,這里是使用“注冊—通知—撤銷注冊”的形式。TimeManager類可以返回一個單例,每一條彈幕作為一個觀察者,注冊到TimeManager類的單例的set表中,當單例的set中有數(shù)據(jù)時,被觀察者狀態(tài)被改變,執(zhí)行動畫,并通知所有觀察者進行update狀態(tài)更新。彈幕移動超過視頻寬度時,從TimeManager中注銷。當TimeManager單例的set表中所有被觀察彈幕都注銷時,setInterval停止執(zhí)行。
1、Bullet.js:
觀察者:實現(xiàn)彈幕樣式,和自身狀態(tài)更新update()方法.
2、TimeManager.js
被觀察者和Subject:可以增加和刪除觀察者對象,狀態(tài)改變時通知所有觀察者并更新狀態(tài)。
3、Player.js
播放器組件:簡單的播放器樣式,控制按鈕等都是默認樣式。。。
4、實現(xiàn)效果:
5、具體實現(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)建播放器上層:包括標題,作者,反饋意見和舉報等。。。。 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,{ // 視頻居中:進度條被拉長,但是視頻不會被拉長,直接居中: height:"100%", width:"100%", }) videoContent.appendChild(video); // 視頻播放和彈幕滾動控制欄:清晰度/倍速/循環(huán)/鏡像/寬屏/網(wǎng)頁全屏/進度條等、、、、、 let videoControlWrap = document.createElement("div"); Object.assign(videoControlWrap.style,{ width:"100%", height:"44px", opacity:"0", position:"relative", bottom:"0", }) // 底部發(fā)送彈幕及設(shè)置發(fā)送彈幕樣式:例如彈幕顏色/字號/滾動/懸停/速度/字體/屏蔽等。。。 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>
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
關(guān)閉頁面window.location事件未執(zhí)行的原因及解決方法
這篇文章主要介紹了關(guān)閉頁面window.location事件未執(zhí)行的原因及解決方法,需要的朋友可以參考下2014-09-09js定時器setInterval、clearInterval的使用方法舉例
Javascript的setTimeOut和clearInterval函數(shù)應(yīng)用非常廣泛,它們都用來處理延時和定時任務(wù),這篇文章主要給大家介紹了關(guān)于js定時器setInterval、clearInterval使用方法的相關(guān)資料,需要的朋友可以參考下2023-11-11javascript中undefined與null的區(qū)別
在JavaScript中存在這樣兩種原始類型:Null與Undefined。這兩種類型常常會使JavaScript的開發(fā)人員產(chǎn)生疑惑,在什么時候是Null,什么時候又是Undefined?2015-08-08總結(jié)Javascript中的隱式類型轉(zhuǎn)換
這篇文章談?wù)凧avaScript的隱式類型轉(zhuǎn)換,我們知道在JavaScript中聲明變量不需指定類型, 對變量賦值也沒有類型檢查,同時JavaScript允許隱式類型轉(zhuǎn)換。這些特征說明JavaScript屬于弱類型的語言。2016-08-08Javascript動手實現(xiàn)call,bind,apply的代碼詳解
這篇文章主要為大家詳細介紹了Javascript動手實現(xiàn)call,bind,apply的代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-02-02js和jquery中循環(huán)的退出和繼續(xù)學習記錄
這篇文章主要介紹了js和jquery中循環(huán)的退出和繼續(xù)學習記錄,下哦功能不簡單,需要的朋友可以參考下2014-09-09JavaScript實現(xiàn)網(wǎng)頁帶動畫返回頂部的方法詳解
這篇文章主要為大家詳細介紹了如何利用JavaScript實現(xiàn)網(wǎng)頁帶動畫返回頂部的效果,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下2022-08-08