JS实现视频弹幕效果

 更新时间:2021年09月10日 11:35:26   作者:weixin_51276799  
这篇文章主要为大家详细介绍了JS实现视频弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

使用ES6的模块化开发及观察者模式来实现。观察者模式有很多种形式,这里是使用“注册—通知—撤销注册”的形式。TimeManager类可以返回一个单例,每一条弹幕作为一个观察者,注册到TimeManager类的单例的set表中,当单例的set中有数据时,被观察者状态被改变,执行动画,并通知所有观察者进行update状态更新。弹幕移动超过视频宽度时,从TimeManager中注销。当TimeManager单例的set表中所有被观察弹幕都注销时,setInterval停止执行。

1、Bullet.js:

观察者:实现弹幕样式,和自身状态更新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",
            position:"relative",
            top:0,
            display:"flex",
            flexDirection:"column",
        })
        // 创建播放器上层:包括标题,作者,反馈意见和举报等。。。。
        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",
        })
        // 视频播放状态开关
        // 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);
 
        // 视频播放和弹幕滚动控制栏:清晰度/倍速/循环/镜像/宽屏/网页全屏/进度条等、、、、、
        let videoControlWrap = document.createElement("div");
        Object.assign(videoControlWrap.style,{
            width:"100%",
            height:"44px",
            opacity:"0",
            position:"relative",
            bottom:"0",
        })
 
        // 底部发送弹幕及设置发送弹幕样式:例如弹幕颜色/字号/滚动/悬停/速度/字体/屏蔽等。。。
        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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 关闭页面window.location事件未执行的原因及解决方法

    关闭页面window.location事件未执行的原因及解决方法

    这篇文章主要介绍了关闭页面window.location事件未执行的原因及解决方法,需要的朋友可以参考下
    2014-09-09
  • js定时器setInterval、clearInterval的使用方法举例

    js定时器setInterval、clearInterval的使用方法举例

    Javascript的setTimeOut和clearInterval函数应用非常广泛,它们都用来处理延时和定时任务,这篇文章主要给大家介绍了关于js定时器setInterval、clearInterval使用方法的相关资料,需要的朋友可以参考下
    2023-11-11
  • javascript中undefined与null的区别

    javascript中undefined与null的区别

    在JavaScript中存在这样两种原始类型:Null与Undefined。这两种类型常常会使JavaScript的开发人员产生疑惑,在什么时候是Null,什么时候又是Undefined?
    2015-08-08
  • 微信小程序自定义toast弹窗效果的实现代码

    微信小程序自定义toast弹窗效果的实现代码

    微信小程序里面的自带弹窗icon只有两种,success和loading。这篇文章主要介绍了微信小程序之自定义toast弹窗效果的实现代码 ,需要的朋友可以参考下
    2018-11-11
  • Bootstrap笔记—折叠实例代码

    Bootstrap笔记—折叠实例代码

    本篇文章主要介绍了Bootstrap笔记—折叠实例代码,详细的介绍了折叠效果实例,包括一组多组等,非常具有实用价值,需要的朋友可以参考下。
    2017-03-03
  • 总结Javascript中的隐式类型转换

    总结Javascript中的隐式类型转换

    这篇文章谈谈JavaScript的隐式类型转换,我们知道在JavaScript中声明变量不需指定类型, 对变量赋值也没有类型检查,同时JavaScript允许隐式类型转换。这些特征说明JavaScript属于弱类型的语言。
    2016-08-08
  • Javascript动手实现call,bind,apply的代码详解

    Javascript动手实现call,bind,apply的代码详解

    这篇文章主要为大家详细介绍了Javascript动手实现call,bind,apply的代码,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • js和jquery中循环的退出和继续学习记录

    js和jquery中循环的退出和继续学习记录

    这篇文章主要介绍了js和jquery中循环的退出和继续学习记录,下哦功能不简单,需要的朋友可以参考下
    2014-09-09
  • js实现多图左右切换功能

    js实现多图左右切换功能

    这篇文章主要介绍了js实现多图左右切换功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • JavaScript实现网页带动画返回顶部的方法详解

    JavaScript实现网页带动画返回顶部的方法详解

    这篇文章主要为大家详细介绍了如何利用JavaScript实现网页带动画返回顶部的效果,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2022-08-08

最新评论