天天看點

原生JS實作移動端彈幕(虎牙,鬥魚簡易版)

話不多說,老規矩,先上Demo 點此預覽

原生JS實作移動端彈幕(虎牙,鬥魚簡易版)

實作思路:

  • 從輸入框擷取輸入資訊
  • 生成彈幕節點
  • 彈幕從螢幕一側逐幀移動到另一側
  • 移動完畢,删除彈幕節點

- 首先是界面布局的實作CSS

*{
           padding: 0;
           margin: 0;
       }
        html,body{
            height: 100%;
            user-select: none;
        }
        .screen{
            overflow: hidden;
            position: relative;
            height: 100%;
            background-color: rgba(249, 249, 249, 0.78);
        }
        .top{
            position: absolute;
            top:0;
            height: 80px;
            width: 100%;
            line-height: 80px;
            background-color: #ffffff;
            text-align: center;
            font-size: 35px;
            font-weight: bold;
            color: rgba(2, 2, 5, 0.87);
            box-shadow: 17px -5px 40px #6d6a6a8f
        }
        .top span{
            position: absolute;
            left: 55px;
            color: #7c22d6;
            font-size: 25px;
        }
        .send{
            position:absolute;
            bottom: 0;
            width:100%;
            height:240px;
            line-height:240px;
            background-color: #ffffff;
            text-align: center;
            box-shadow: 17px 11px 40px #6d6a6a8f;
        }
        .input{
            position: absolute;
            left:50%;
            top:50%;
            margin: -65px -446px;
            font-size: 25px;
        }
        .text{
            float: left;
            width: 584px;
            height: 74px;
            border: none;
            border-radius:109px;
            font-size: 35px;
            background-color: rgba(17, 22, 45, 0.04);
        }
        .btn{
            float:left;
            margin-left: 30px;
            height: 74px;
            width: 74px;
            background-color: rgba(135, 17, 208, 0.88);
            line-height: 74px;
            font-size: 35px;
            color: #eeeeee;
            cursor: pointer;
            border-radius:22px;
            box-shadow:6px 7px 12px -1px #968f96db;
        }

       .say{
           float: right;
           margin-left: 30px;
           width: 160px;
           height: 91px;
           font-size: 38px;
           font-weight: bold;
           line-height: 91px;
           color: #9f2dee;
           cursor: pointer;
           border-radius:62px;
       }
        .s_show div{
            position: absolute;
            font-size: 40px;
            font-weight: bold;
            color: rgba(3, 5, 2, 0.5);
        }
       .btn:hover{
           float: left;
           margin-left: 32px;
           width: 65px;
           background-color: rgba(31, 208, 185, 0.88);
           line-height: 65px;
           font-size: 35px;
           color: #eeeeee;
           cursor: pointer;
           border-radius:15px;
       }
           

html界面的實作

<div class="screen">
    <div class="top">
        Live Show
    </div>
    <div class="send">
        <div class="input">
            <input type="text" class="text" placeholder="    Say   Something   ...">
            <div class="btn" id="btn">
            </div>
            <div class="say">SEND</div>
        </div>
    </div>
    <div class="s_show">
        <div>讓開!擋到我用無限屏了</div>
        <div>主播求微信</div>
        <div>來了老弟</div>
        <div>7777777777777777777777777</div>
        <div>求求你,不要秀了</div>
        <div>這也太真實了吧</div>
    </div>
</div>
           

js的實作

(function () {
            //擷取所有需要的節點
            let sShowList = document.querySelectorAll('.s_show div'),
                oSend = document.querySelector('.send'),
                oShow = document.querySelector('.s_show'),
                oText = document.querySelector('.text'),
                otop = document.querySelector('.top'),
                oBtn = document.querySelector('.btn'),
                oTime = 0,//初始化點選時間,用來限制點選頻率
                waitTime = 3;

            oBtn.onclick = function () {
                if (new Date() - oTime > 3000 && oText.value) {//點選間隔大于3秒
                    let Div = document.createElement('div');
                    Div.innerHTML = oText.value;
                    oShow.appendChild(Div);//添加彈幕節點
                    init(Div);//初始化彈幕效果
                    oTime = new Date();
                }
            };

            for (i = 0; i < sShowList.length; i++) {//周遊所有已有彈幕節點,初始化
                init(sShowList[i])
            }

            function init(obj) {
                var screenHeight = document.documentElement.clientHeight,
                    screenWidth = document.documentElement.clientWidth,//螢幕寬高
                    sendHeight = oSend.clientHeight,//輸入界面高度
                    topHeight = otop.clientHeight,//标題欄高度
                    height = screenHeight - sendHeight - obj.clientHeight - topHeight,//彈幕顯示區域高度
                    width = screenWidth - obj.clientWidth;

                obj.style.top = Math.random() * height + topHeight + 'px';//+topHeight 是為了讓彈幕不被标題欄遮住
                obj.style.left = width + 'px';
                move(obj, width);
            }
            //動畫效果
            function move(obj, width) {
                if (width > -obj.clientWidth) {
                    width -= 2;
                    obj.style.left = width + 'px';
                    requestAnimationFrame(function () {
                        move(obj, width);
                    });//生成動畫,2px移動
                } else {
                    oShow.removeChild(obj);//如果彈幕顯示寬度小于0—obj.width ,移除該節點。
                }
            }
        })();
           

為了防止頻繁發送,可以給發送時間添加定時器。通過與上次點選的時間差, 判斷是否進行彈幕的擷取。

具體注釋都已經在上面代碼中進行标注講解

最後,預覽位址blogai.cn