利用面向对象写弹幕效果

利用面向对象写弹幕效果

<!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>
        .container {
     
     
            width: 800px;
            margin: 0 auto;
            padding-bottom: 10px;
            background-color: #dfdfdf;
        }
        
        #barrage {
     
     
            position: relative;
            height: 500px;
            margin-bottom: 10px;
            background-color: #000;
            overflow: hidden;
        }
        
        #barrage .bar-item {
     
     
            position: absolute;
            left: 100%;
            white-space: nowrap;
        }
        
        #msg {
     
     
            margin-left: 10px;
            width: 400px;
            height: 30px;
            border: 1px solid #999;
            border-right: none;
            box-sizing: border-box;
            vertical-align: middle;
        }
        
        #msg+button {
     
     
            padding: 0 10px;
            height: 30px;
            vertical-align: middle;
        }
    </style>
</head>

<body>
    <div class="container">
        <div id="barrage"></div>
        <input type="text" id="msg"><button id="btn">发送</button>
    </div>

    <script src="js/utils.js"></script>
    <script>
        /*
        【1】创建对象 (弹幕的文字)
        【2】描述对象
            静态属性:
                在页面中存在的标签
                弹幕的内容(文字)
                文字的大小
                文字的颜色
                文字的位置
                文字移动速度
            动态方法:
                init() 初始化的方法,一般用来写事件,获取元素,创建节点,调用方法
                move() 文字移动的函数
                removeEle() 当文字移动到 弹幕之外移出这个弹幕的元素
        【3】操作对象
    */
        // 创建对象
        function Barrage(ele, content) {
     
     
            this.ele = ele;
            this.content = content;
            this.fontSize = getRandom(12, 30);
            this.color = getRandomColor();
            this.top = getRandom(0, this.ele.offsetHeight - this.fontSize);
            this.speed = getRandom(10, 20);
        }

        // 动态方法一般写在原型对象上面
        Barrage.prototype.init = function() {
     
     
            // 创建一个节点 span
            this.span = document.createElement('span');
            this.span.classList.add('bar-item');
            this.span.innerHTML = this.content;
            this.span.style.fontSize = this.fontSize + 'px';
            this.span.style.color = this.color;
            this.span.style.top = this.top + 'px';
            this.ele.appendChild(this.span);

            this.move()
        }

        // 弹幕移动效果
        Barrage.prototype.move = function() {
     
     
            let timer = setInterval(() => {
     
     
                // 获取当前的left值
                let styleLeft = parseInt(getStyle(this.span, 'left'));
                console.log(styleLeft)
                    // 当当前的left值 小于 span元素宽度的负值时清除定时器,并且移出span元素
                if (styleLeft <= -this.span.offsetWidth) {
     
     
                    clearInterval(timer);
                    this.removeEle();
                }
                move(this.span, {
     
     
                    left: styleLeft - this.speed
                })
            }, 80)

            // let _this = this;
            // let timer = setInterval(function () {
     
     
            //     // this指向的是window window 中没有span属性
            //     console.log(_this);
            //     let styleLeft = parseInt(getStyle(_this.span, 'left'));
            //     if (styleLeft <= -_this.span.offsetWidth) {
     
     
            //         clearInterval(timer);
            //         _this.removeEle();
            //     }
            //     move(_this.span, { left: styleLeft - _this.speed })
            // }, 80)

        }

        // 当移动结束 把这个节点移出
        Barrage.prototype.removeEle = function() {
     
     
            // 移出span元素
            this.span.remove()
        }


        // 获取页面中存在的标签
        let barrage = document.querySelector('#barrage');
        let btn = document.querySelector('#btn');
        let msg = document.querySelector('#msg');

        // 给btn绑定点击事件
        btn.onclick = function() {
     
     
            let b = new Barrage(barrage, msg.value);
            b.init();
            msg.value = '';
        }



// 获取一个随机颜色
function getRandomColor() {
     
     
    // var str = '0123456789abcdef';
    // var res = '#'
    // for (var i = 0; i < 6; i++) {
     
     
    //     // str[索引] 这个索引是随机,在0-15范围之间随机
    //     res += str[parseInt(Math.random() * 16)]
    // }
    var r1 = parseInt(Math.random() * 256);
    var r2 = parseInt(Math.random() * 256);
    var r3 = parseInt(Math.random() * 256);
    var res = `rgb(${
       
       r1},${
       
       r2},${
       
       r3})`
    return res;
}


// 获取样式的方法
// 有两个参数
// 参数1:元素
// 参数2:csss属性
function getStyle(ele, attr) {
     
     
    return style = window.getComputedStyle ? window.getComputedStyle(ele)[attr] : ele.currentStyle[attr]
}


// 封装一个事件监听的函数(兼容)
// 参数:事件源,事件类型,回调函数
function addEvent(ele, type, callback) {
     
     
    if (ele.addEventListener) {
     
     
        ele.addEventListener(type, callback);
    } else {
     
     
        ele.attachEvent('on' + type, callback)
    }
}

// 动画函数
function move(ele, obj, callback) {
     
     
    let speed;
    let index = 0; //记录定时器的个数
    // 循环对象创建定时器
    for (let attr in obj) {
     
     
        // 透明度的变化的时候 0-1
        // console.log(attr);
        index++;
        // 清除上一次的定时器
        clearInterval(ele[attr])
        // 属性:attr
        // 属性值:obj[key]
        // box['width'] 给box这个dom元素添加一个 width属性(dom属性)
        // dom 对象,以地址形式存储的,当上一次更改dom对象中的值,那么这次获取这个对象的时候是能拿到被更改之后的dom对象
        ele[attr] = setInterval(() => {
     
     
            // 把透明度的取值 改边为0-100的取值
            // 0-1=====》0-100
            let style;
            if (attr == 'opacity') {
     
     
                style = getStyle(ele, attr) * 100;
            } else {
     
     
                style = parseInt(getStyle(ele, attr));
            }

            speed = (obj[attr] - style) / 5;
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed);
            style += speed;


            if (attr === 'opacity') {
     
     
                ele.style[attr] = style / 100;
            } else {
     
     
                ele.style[attr] = style + 'px';
            }

            if (style == obj[attr]) {
     
     
                clearInterval(ele[attr]);
                // 有多少个属性参数动画就会执行多少次
                // 执行一次怎么?
                // 没清除一次定时器,那么定时器的个数 -1
                index--;
                // 当定时器的个数 为0 的时候,说明所有动画执行完毕
                if (index === 0) {
     
     
                    callback && callback();
                }
            }
        }, 50)
    }
}

    </script>
</body>

</html>

猜你喜欢

转载自blog.csdn.net/weixin_43901780/article/details/108092679