【JS】原生JS模拟弹幕效果--普通写法,构造函数,class

效果图

在这里插入图片描述

公用部分

html

<div id="box">
        <video src="../video/film2.mp4" controls id="film" autoplay muted loop></video>
        <input type="text" placeholder="发个友善的弹幕见证当下" class="dm">
        <input type="button" id="btn" value="发送" class="btn" />
        <!-- <span>123</span> -->
    </div>

CSS

* {
            margin: 0;
            padding: 0;
        }

        #box {
            width: 1000px;
            height: 800px;
            margin: 0 auto;
            position: relative;
            overflow: hidden;
        }

        #film {
            width: 100%;
        }

        .dm {
            box-sizing: border-box;
            width: 80%;
            height: 30px;
            border: none;
            position: absolute;
            bottom: 180px;
            left: 100px;
            padding: 20px;
            background-color: #ccc;
        }

        .btn {
            position: absolute;
            box-sizing: border-box;
            width: 60px;
            height: 40px;
            border: none;
            background-color: red;
            color: white;
            font-weight: 700;
            bottom: 180px;
            left: 900px;
        }

        span {
            position: absolute;
            white-space: nowrap;
            left: 20px;
            border: 2px double white;
        }
    </style>

不同方法实现功能

普通方法

//获取元素
    let boxObj = document.querySelector('#box');//获取最外层盒子
    let filmObj = document.querySelector('#film');//获取视频元素
    let dmObj = document.querySelector('.dm');//获取弹幕输入框
    let btnObj = document.querySelector('.btn');//获取发送按钮
    let maxH = filmObj.offsetHeight;//获取视频的宽度,为弹幕设置高度范围
    let speed = 10;//步进值
    //单击
    btnObj.onclick = function () {
        //如果输入不为空
        if (dmObj.value != '') {
            move();
        }
    }
    //回车
    document.onkeydown = function (eve) {
        //如果按下的是回车键
        if (eve.keyCode == 13&&dmObj.value!='') {
            move();
        }
    }

    //弹幕函数
    function move() {
        //获取盒子的宽度,设置为弹幕初始left值
        let maxW = boxObj.offsetWidth;
        //创建节点
        let newSpan = document.createElement('span');
        //获取输入框的值写入span
        newSpan.innerHTML = dmObj.value.trim();
        //弹幕随机颜色
        newSpan.style.color = getColor();
        //弹幕高度值随机,范围为0,到盒子高度
        newSpan.style.top = getNum(0, maxH) + 'px';
        //弹幕left值
        newSpan.style.left = maxW + 200 + 'px';
        //弹幕字体大小随机
        newSpan.style.fontSize = getNum(16, 26) + 'px';
        //追加到页面中
        boxObj.appendChild(newSpan);
        //获取span宽度
        let dmW = newSpan.offsetWidth;
        console.log(dmW);
        //设置定时器
        let times = setInterval(function () {
            //left值减
            maxW -= speed;
            //如果弹幕left值小于负的弹幕宽度,即弹幕已经移动到视频外部
            if (maxW < (-dmW)) {
                clearInterval(times);//清除计时器
            }
            //将减后的left值赋值
            newSpan.style.left = maxW + 'px';
        }, 100)
        //输入框清空
        dmObj.value = '';
    }
    //获取十六进制随机色
    function getColor() {
        var a = "#";
        var c = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
        for (var i = 0; i < 6; i++) {
            a += c[getNum(0, 15)];
        }
        return a;
    }
    //获取指定范围内的随机数
    function getNum(num1, num2) {
        var max, min;
        if (num1 > num2) {
            max = num1;
            min = num2;
        } else {
            max = num2;
            min = num1;
        }
        return Math.round(Math.random() * (max - min) + min);
    }

构造函数

function Barrage() {
        //获取节点
        this.box = document.querySelector('#box');
        this.video = document.querySelector('#film');
        this.dm = document.querySelector('.dm');
        this.btn = document.querySelector('.btn');
        //获取视频高度
        this.maxH = this.video.offsetHeight;
        //获取视频宽度,作为弹幕初始left值,
        this.maxW = this.video.offsetWidth;
        // console.log(this.maxH);
        this.speed = 10;//步进值
        // console.log(this);
        //单击事件
        this.btn.addEventListener('click', this.clickFn.bind(this));
        //回车事件
        window.addEventListener('keydown', this.keydownFn.bind(this));
    }
    //单击事件
    Barrage.prototype.clickFn = function () {
        if (this.dm.value != '') {
            this.move();
        }
    }
    //回车事件
    Barrage.prototype.keydownFn = function (eve) {
        // console.log(this);
        eve = eve || window.event;
        if (eve.keyCode == 13 && this.dm.value != '') {
            this.move();
        }
    }
    //移动事件
    Barrage.prototype.move = function () {
        //创建节点
        let newSpan = document.createElement('span');
        //节点内容为输入框输入内容
        newSpan.innerHTML = this.dm.value;
        newSpan.style.color = this.getColor();//颜色随机
        newSpan.style.top = this.getNum(0, this.maxH) + 'px';//高度随机
        //距左边的间距设为视频宽度,后期减减,实现弹幕效果
        newSpan.style.left = this.maxW + 'px';
        //字体大小随机
        newSpan.style.fontSize = this.getNum(14, 34) + 'px';
        //追加到页面上
        this.box.appendChild(newSpan);
        //获取追加弹幕的宽度
        let dmWidth = newSpan.offsetWidth;
        //因为计时器内部this必须指向window,
        //所以需要获取最大宽度和步进值并重新赋值
        let maxW = this.maxW;
        let speed = this.speed;
        //开启定时器,实现弹幕效果
        let times = setInterval(function () {
            maxW -= speed;
            if (maxW < -dmWidth) {
                clearInterval(times);
            }
            newSpan.style.left = maxW + 'px';
        }, 100)
        this.dm.value = '';
    }

    //获取十六进制随机色
    Barrage.prototype.getColor = function () {
        var a = "#";
        var c = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
        for (var i = 0; i < 6; i++) {
            a += c[this.getNum(0, 15)];
        }
        return a;
    }
    //获取指定范围内的随机数
    Barrage.prototype.getNum = function (num1, num2) {
        var max, min;
        if (num1 > num2) {
            max = num1;
            min = num2;
        } else {
            max = num2;
            min = num1;
        }
        return Math.round(Math.random() * (max - min) + min);
    }
    new Barrage();

class

class Barrage {
        //获取元素
        video = document.querySelector('#film');
        dm = document.querySelector('.dm');
        btn = document.querySelector('.btn');
        box = document.querySelector('#box');
        //获取视频宽度作为弹幕初始left值
        maxH = this.video.offsetHeight;
        //获取视频高为设置弹幕随机高度做准备
        maxW = this.video.offsetWidth;
        speed = 10;//步进值
        constructor() {
            //点击事件
            btn.addEventListener('click', this.clickFn.bind(this));
            //回车事件
            document.addEventListener('keydown', this.keydownFn.bind(this));

        }
        //单击事件
        clickFn() {
            //如果输入框内值不为空执行弹幕移动函数
            if (this.dm.value != '') {
                this.move();
            }
        }
        //回车事件
        keydownFn() {
            //如果按下回车键且输入框内值不为空执行弹幕移动函数
            if (window.event.keyCode == 13 && this.dm.value != '') {
                this.move();
            }
        }
        //弹幕移动
        move() {
            //创建节点
            let newSpan = document.createElement('span');
            //高度随机
            newSpan.style.top = this.getNum(0, this.maxH) + 'px';
            //设置left初始值
            newSpan.style.left = this.maxW + 'px';
            //颜色随机
            newSpan.style.color = this.getColor();
            //字体大小随机
            newSpan.style.fontSize = this.getNum(16, 36) + 'px';
            //将输入框内输入值作为节点内容
            newSpan.innerHTML = this.dm.value;
            //追加到页面上
            this.box.appendChild(newSpan);
            //获取弹幕宽度为弹幕移动设置边界
            let minLeft = newSpan.offsetWidth;
            //计时器内this必须指向window才能避免计时器累加,
            //但指向windowclass内定义的属性不能直接使用,
            //所以在这里将class内定义的属性值重新声明一个变量赋值来使用
            let left = this.maxW;
            let speed = this.speed;
            //设置计时器实现弹幕效果
            let times = setInterval(function () {
                left -= speed;//left值--
                //如果left值小于负的弹幕宽度,说明弹幕已经移出视频,清除计时器
                if (left < -minLeft) {
                    clearInterval(times);
                }
                //left值不断变化
                newSpan.style.left = left + 'px';
            }, 100);
            //每点一次发送,清空一次输入框内的值
            this.dm.value = '';
        }
        //获取随机颜色
        getColor() {
            var a = "#";
            var c = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];
            for (var i = 0; i < 6; i++) {
                a += c[this.getNum(0, 15)];
            }
            return a;
        }
        //获取随机范围内的数字
        getNum(num1, num2) {
            var max, min;
            if (num1 > num2) {
                max = num1;
                min = num2;
            } else {
                max = num2;
                min = num1;
            }
            return Math.round(Math.random() * (max - min) + min);
        }
    }
    new Barrage();
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值