美文网首页
弹幕插件编写

弹幕插件编写

作者: Martin_Luo | 来源:发表于2019-10-16 17:22 被阅读0次
  • 注意:该插件依赖于jQuery

HTML和CSS代码

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>简单实用文字弹幕</title>
    <style type="text/css">
        html {
          color: #fff;
          -webkit-text-size-adjust: 100%;
          -ms-text-size-adjust: 100%;
          background: #cf6a6d;
          background: linear-gradient(to right, #f6ad32, #cf6a6d);
        }
        body {
            margin: 0;
            min-width: 960px;
        }
        html, body {
            height: 100%;
            overflow: hidden;
        }
        input, button {
            border: none;
            outline: none;
        }
        .clearfix::after {
            content: '';
            height: 0;
            display: table;
            visibility: hidden;
            clear: both;
        }
        .container {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
        }
        .input-box {
            position: absolute;
            left: 0;
            right: 0;
            bottom: 0;
            z-index: 1;
            height: 40px;
            padding: 30px 0;
            text-align: center;
            background: rgba(0,0,0,.6);
        }
        .input-box input {
            width: 320px;
            height: 40px;
            padding: 0 10px;
            font-size: 16px;
            border-radius: 10px;
            color: #333;
            transition: box-shadow .5s;
        }
        .input-box .btn {
            width: 100px;
            height: 40px;
            line-height: 40px;
            margin-left: 10px;
            border-radius: 10px;
            font-weight: bold;
            color: #fff;
            font-size: 16px;
            background: #cf6a6d;
            background: linear-gradient(to right, #f6ad32, #cf6a6d);
            cursor: pointer;
            transition: box-shadow .5s;
        }
        .list {
            position: absolute;
            left: 100%;
            white-space: nowrap;
            line-height: 32px;
            font-size: 18px;
            color: #fff;
            text-shadow: 0 0 3px #000;
            transition: transform 25s linear;
        }
        .list.animate {
            transform: translateX(-3420px);
        }
        .container .list img {
          width: 24px;
          height: 24px;
          margin-right: 5px;
          border-radius: 50%;
          vertical-align: text-top;
        }
    </style>
</head>
<body>
    <div class="container" id="container"></div>
    
    <div class="input-box">
        <input type="text" maxlength="20" placeholder="说点什么吧~"/>
        <button class="btn" id="btn">发送</button>
    </div>
    
    <script src="js/jquery-1.10.2.min.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/barrageWall.js" type="text/javascript" charset="utf-8"></script>
    
    <script type="text/javascript">
        // 实例化弹幕墙
        var send = new BarrageWall({
            container: '#container',
            barrageLen: 10
        });
        // 发送弹幕
        send.upWall('图片路径.png', '小菜基', '发表想法');
        
        // 发送弹幕
        $('#btn').click(function () {
            var $oIpt = $(this).prev(), // 获取input元素
                val = $oIpt.val().trim(); // 获取input值
            send.upWall('images/aq.png', '小菜基', val);
            $oIpt.val(''); // 清空输入内容
        })
        
        // 通过定时器模拟用户输入
        var i = 0,
            t = null;
        t = setInterval(function () {
            if (i > 10) {
                clearInterval(t);
            }
            send.upWall('图片路径.png', '小菜基'+ i +'号', '发表个'+ i +'感想.');
            i++;
        }, 300);
    </script>
</body>
</html>

barrageWall.js 代码

;(function () {
    var BarrageWall = function (opt) {
        this.init(opt);
    }
    
    BarrageWall.prototype = {
        init: function (opt) {
            if (!opt.container) {
                throw new Error('必须指定 container 属性,container为弹幕容器的选择器');
            }
            if (opt.barrageLen < 1) {
                throw new Error('必须指定barrageLen属性,barrageLen为弹幕的轨道数');
            }
            this.container = opt.container; // 弹幕容器
            this.barrageLen = opt.barrageLen; // 轨道数
            this.lastElem = 0; // 弹幕出现的位置
            this.barrage = []; //弹幕墙
            this.barrageOffset = []; // 弹幕墙上最后一条弹幕的偏移量
            
            for (var i = 0; i < opt.barrageLen; i++) {
                this.barrage.push([])
            }
        },
        upWall: function (img, user, txt) {
            this.positionWall(); // 从上至下找出每条弹幕轨道上最后一条弹幕移动位置
            
            var elem = $('<div></div>') // 创建元素
                    .addClass('list')               // 添加样式
                    .css('top', this.lastElem * 38 + 'px'); // 定位
            elem.html('<img src='+ img +' alt="" />'+ user + ':' + txt) // 添加内容
                    .appendTo(this.container); // 追加在父元素后面
                    
            this.barrage[this.lastElem].push(elem); // elem追加在数组中
            
            // 延迟200ms添加动画,防止元素动画不执行
            setTimeout(function () {
                elem.addClass('animate')
            }, 200)
            
            // 25s后动画执行完毕,从数组和页面中移除
            setTimeout(function () {
                var item,
                    flag = false;
                for (var i = 0; i < this.barrageLen; i++) {
                    item = this.barrage[i];
                    if (flag) {
                        break; // true 跳出循环
                    }
                    for (var j = 0; j < item.length; j++) {
                        if (item[j] === elem) {
                            this.barrage[i].splice(j, 1);
                            flag = true;
                            break; // 满足条件跳出当前循环
                        }
                    }
                }
                elem.remove(); // 移除自己
            }, 25000)
        },
        positionWall: function () {
            // 从上至下找出每条弹幕轨道上最后一条弹幕移动位置
            var len = this.barrageLen;
            for (var i = 0; i <= len; i++) {
                if (i === len) { // 弹幕队列超过弹道数进入
                    this.minOffset()// 弹幕墙上所有的位置都有弹幕且都未出现完毕时,找出他们当中完全最先的那个
                } else {
                    // 找到弹幕出现的位置,找到退出循环
                    if (this.afterOffset(i)) {
                        break;
                    }
                }
            }
        },
        afterOffset: function (i) { // 找到弹幕出现的位置
            if (this.barrage[i].length === 0) {
                this.lastElem = i;
                return true;
            } else { // 轨道有数据
                var elem = this.barrage[i][this.barrage[i].length - 1], // 获取当前弹幕轨道上最后一条弹幕
                        aboveWidth = elem.width(), // 获取它的宽度
                        matrix = elem.css('transform'); // 获取它的矩阵值
                if (matrix !== 'none') {
                    var aboveTransform = parseInt(matrix.split(',')[4]); // 取出最后一条弹幕的矩阵值中X轴的偏移量,即translateX
                    // 50为间隔,为true则表示当前弹幕轨道上最后一条弹幕已经全部出现,则当前弹幕放在该轨道上
                    if (-aboveTransform - aboveWidth > 50) {
                        this.lastElem = i;
                        return true;
                    }
                }
            }
            return false;
        },
        minOffset: function () { // 弹幕墙上所有的位置都有弹幕且都未出现完毕时,找出他们当中完全最先的那个
            var minOffset = 0,
                    item;
            for (var i = 0; i < this.barrageLen; i++) { // 遍历比较弹幕墙,找出队列最远的那个元素
                item = this.barrage[i];
                
                var elem = item[item.length - 1], // 获取当前弹幕轨道上最后一条弹幕
                        aboveWidth = elem.width(), // 获取它的宽度
                        matrix = elem.css('transform'); // 获取它的矩阵值
                this.barrageOffset[i] = matrix === 'none' ? -aboveWidth : -parseInt(matrix.split(',')[4]) - aboveWidth;
                minOffset = this.barrageOffset[i] > this.barrageOffset[minOffset] ? i : minOffset;
            }
            this.lastElem = minOffset;
        }
    }
    
    window.BarrageWall = BarrageWall;
})();

如有不足或更好的方式实现,欢迎大家留言探讨

相关文章

网友评论

      本文标题:弹幕插件编写

      本文链接:https://www.haomeiwen.com/subject/cngqjqtx.html