ubuntu16.04下workerman-gateway實現(xiàn)長連接彈幕系統(tǒng)聊天室案例

彈幕系統(tǒng)聊天室

gateway介紹

  • GatewayWorker基于Workerman開發(fā)的一個項目框架腿椎,用于快速開發(fā)TCP長連接應用优烧,例如app推送服務端、即時IM服務端庸娱、游戲服務端着绊、物聯(lián)網、智能家居等等

  • GatewayWorker使用經典的Gateway和Worker進程模型熟尉。Gateway進程負責維持客戶端連接归露,并轉發(fā)客戶端的數據給BusinessWorker進程處理,BusinessWorker進程負責處理實際的業(yè)務邏輯(默認調用Events.php處理業(yè)務)斤儿,并將結果推送給對應的客戶端剧包。Gateway服務和BusinessWorker服務可以分開部署在不同的服務器上,實現(xiàn)分布式集群往果。

  • GatewayWorker提供非常方便的API疆液,可以全局廣播數據、可以向某個群體廣播數據陕贮、也可以向某個特定客戶端推送數據堕油。配合Workerman的定時器,也可以定時推送數據肮之。

環(huán)境搭建

下載安裝gateway

root@iZwz94dunl1qornhtnn4gpZ:/www/web/default# wget -c http://www.workerman.net/download/GatewayWorker.zip

root@iZwz94dunl1qornhtnn4gpZ:/www/web/default# unzip GatewayWorker.zip

root@iZwz94dunl1qornhtnn4gpZ:/www/web/default# cd GatewayWorker

協(xié)議以及地址

  • 注意
ip:

1掉缺、如果寫0.0.0.0代表監(jiān)聽本機所有網卡,也就是內網戈擒、外網眶明、本機都可以訪問到

2、如果是127.0.0.1峦甩,代表只能本機通過127.0.0.1訪問赘来,外網和內網都訪問不到

3现喳、如果是內網ip例如:192.168.10.11,代表只能通過192.168.10.11訪問犬辰,也就是只能內網訪問嗦篱,本機127.0.0.1也訪問不了(如果監(jiān)聽的ip不屬于本機則會報錯)

4、如果是外網ip例如110.110.110.110幌缝,代表只能通過外網ip 110.110.110.110訪問灸促,內網和本機127.0.0.1都訪問不了(如果監(jiān)聽的ip不屬于本機則會報錯)

port:

端口不能大于65535,請確認端口沒有被其它程序占用涵卵,否則啟動會報錯浴栽。如果端口小于1024,需要root權限運行GatewayWorker才能有權限監(jiān)聽轿偎,否則報錯沒有權限典鸡。
  • 修改start_gateway.php文件配置協(xié)議地址
root@iZwz94dunl1qornhtnn4gpZ:/www/web/default/GatewayWorker# vim Applications/YourApp/start_gateway.php

文件內容
<?php
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link http://www.workerman.net/
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */
use \Workerman\Worker;
use \Workerman\WebServer;
use \GatewayWorker\Gateway;
use \GatewayWorker\BusinessWorker;
use \Workerman\Autoloader;

// 自動加載類
require_once __DIR__ . '/../../vendor/autoload.php';
$gateway = new Gateway("websocket://0.0.0.0:8081");
// gateway名稱,status方便查看
$gateway->name = 'Lottery-2019';
// gateway進程數
$gateway->count = 4;
// 本機ip坏晦,分布式部署時使用內網ip
$gateway->lanIp = '127.0.0.1';
// 內部通訊起始端口萝玷,假如$gateway->count=4,起始端口為4000
// 則一般會使用4000 4001 4002 4003 4個端口作為內部通訊端口 
$gateway->startPort = 2900;
$gateway->registerAddress = '127.0.0.1:1238';


// 當客戶端連接上來時昆婿,設置連接的onWebSocketConnect球碉,即在websocket握手時的回調
$gateway->onConnect = function($connection)
{
    $connection->onWebSocketConnect = function($connection , $http_header)
    {
         var_dump($_GET, $_SERVER);
    };
};


// 如果不是在根目錄啟動,則運行runAll方法
if(!defined('GLOBAL_START'))
{
    Worker::runAll();
}

服務器消息處理

當客戶端有信息發(fā)送過來時仓蛆,聊天室需要立即處理信息并廣播給當前連接了服務器的所有人

  • 修改Events.php
<?php
/**
 * This file is part of workerman.
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the MIT-LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @author walkor<walkor@workerman.net>
 * @copyright walkor<walkor@workerman.net>
 * @link http://www.workerman.net/
 * @license http://www.opensource.org/licenses/mit-license.php MIT License
 */

/**
 * 用于檢測業(yè)務代碼死循環(huán)或者長時間阻塞等問題
 * 如果發(fā)現(xiàn)業(yè)務卡死睁冬,可以將下面declare打開(去掉//注釋),并執(zhí)行php start.php reload
 * 然后觀察一段時間workerman.log看是否有process_timeout異常
 */
//declare(ticks=1);

use \GatewayWorker\Lib\Gateway;
/**
 * 主邏輯
 * 主要是處理 onConnect onMessage onClose 三個方法
 * onConnect 和 onClose 如果不需要可以不用實現(xiàn)并刪除
 */
class Events
{
    /**
     * 當客戶端連接時觸發(fā)
     * 如果業(yè)務不需此回調可以刪除onConnect
     * 
     * @param int $client_id 連接id
     */
//    public static function onConnect($client_id)
//    {
//        // 向當前client_id發(fā)送數據
//        Gateway::sendToClient($client_id, "Hello $client_id\r\n");
//        // 向所有人發(fā)送
//        Gateway::sendToAll("$client_id login\r\n");
//    }
/**
    * 當客戶端發(fā)來消息時觸發(fā)
    * @param int $client_id 連接id
    * @param mixed $message 具體消息
    */
   public static function onMessage($client_id, $message)
   {
        // 向所有人發(fā)送 \n表示字符串結束
        Gateway::sendToAll("$message\n");
   }

   /**
    * 當用戶斷開連接時觸發(fā)
    * @param int $client_id 連接id
    */
   public static function onClose($client_id)
   {
       // 向所有人發(fā)送 
//       GateWay::sendToAll("$client_id logout\r\n");
   }
}

運行服務器

后臺運行聊天室
root@iZwz94dunl1qornhtnn4gpZ:/www/web/default/GatewayWorker# php start.php start -d

建立移動端聊天室

下面代碼重的靜態(tài)資源我這里就先不提供了看疙,各位看官自行修改一下就行了豆拨。
里面有一些代碼涵蓋了以前的紅包系統(tǒng)等,看官可無視狼荞。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>翰文聊天室</title>
    <meta name="viewport" content="width=device-width, initial-scale=1,user-scalable=no">
    <script type="text/javascript">
        // 取消橡皮筋事件
        // document.addEventListener('touchstart', function (e) {
        //   e.preventDefault();
        // });
    </script>
    <style type="text/css">

        html {
            font-family:Helvetica;
            font-size:62.5%;
            color:#222;    /**不建議使用純黑辽装,會顯得呆板**/
            background-image: url(__STATIC__/img/wechat_bg.png);
            background-position: 0 0;
            background-size: 100% 100%;
        }
        html,body {
            margin:0;
            padding:0;
            height:100%;
            width:100%;
        }
        ::selection{
            background-color: #b3d4fc;  /*被選中的背景*/
            text-shadow: none;  /*被選中的陰影*/
        }

        /*設置無序列表的樣式*/
        ul {
            margin: 0;
        }
        li {
            list-style: none;
        }
        input {
            tap-highlight-color:rgba(0,0,0,0);;
            -webkit-tap-highlight-color:rgba(0,0,0,0);
        }
    </style>
    <style type="text/css">
        body {
            position:relative;
        }
        /*聊天內容區(qū)*/
        .cont-box {
            width:100%;
            height:90%;
            position:absolute;
            left:0;
            top:0;
            padding:0 2rem .5rem;
            box-sizing: border-box;
            font-size:1.6rem;
            overflow-y: auto;
            overflow-x: hidden;
        }
        #weChatBody {
            height:auto;
        }
        .cont-box div {
            /*border:1px solid blue;*/
            margin-top:12px;
        }
        /*昵稱*/
        .cont-box div .nickname {
            color: #fb6846;
        }
        /*內容*/
        .cont-box div .content {
            /*color: #fb6846;*/
        }
        /*聊天輸入區(qū)域*/
        .input-box {
            position:fixed;
            /*height:2rem;*/
            width:100%;
            left:0;
            bottom:0;
            border-top:1px solid #fcad9b;
            border-bottom:1px solid #fcad9b;
        }

        .i-box {
            padding:1rem;
            display:flex;
            display:-webkit-flex;
            flex-direction:row;
            justify-content: space-around;
            align-items: center;
            flex-wrap:nowrap;
            background-color: rgba(255,255,255,.5);
        }
        .i-box .b-item {
            height:2.8rem;
            line-height: 2.8rem;
            font-size:1.6rem;
            position:relative;
            overflow: hidden;
            border:1px solid #fb6846;
        }
        .i-box .item1{
            width:10%;
            border-radius:5rem;
            font-size:1.2rem;
            text-align:center;
            color:#fb6846;
        }
        .i-box .item2{
            width:60%;
            border-radius:10px;
            padding:0 5px;
            box-sizing: border-box;
        }
        .i-box .item3{
            width:13%;
            padding:0 5px;
            height:2.8rem;
            border-radius:5px;
            text-align:center;
            white-space:nowrap;
            color:#fff;
            background-color:#ddd;
            border:1px solid #ddd;
        }
        /*輸入框*/
        .item-input {
            overflow: hidden;
            background-color:#fff;
            border:none;
            outline: none;
            /*border:1px solid #eee;*/
            white-space:nowrap;
            tap-highlight-color:rgba(0,0,0,0);
            -webkit-tap-highlight-color:rgba(0,0,0,0);
        }

        /*更換樣式*/
        .input-style {
            height:0;
            width:100%;
            background-color:#fff;
            display:flex;
            overflow: hidden;
            display:-webkit-flex;
            flex-direction:row;
            justify-content: space-around;
            align-items: center;
            flex-wrap:wrap;
            transition:.2s;
            -webkit-transition:.2s;
        }
        .s-item {
            width:27%;
            height:5rem;
            position:relative;
        }
        .input-style .s-item:nth-of-type(1) {
            background-color:#222;
        }
        .input-style .s-item:nth-of-type(2) {
            background-color:#ff0002;
        }
        .input-style .s-item:nth-of-type(3) {
            background-color:#fcff00;
        }
        .input-style .s-item:nth-of-type(4) {
            background-color:#1eff00;
        }
        .input-style .s-item:nth-of-type(5) {
            background-color:#096bff;
        }
        .input-style .s-item:nth-of-type(6) {
            background-color:#ff00d5;
        }
        .input-style .active {
            opacity:.7;
        }
        .input-style .active i {
            position:absolute;
            opacity:.7;
            bottom:0;
            right:0;
            height:3rem;
            width:3rem;
            background-image: url(__STATIC__/img/style_choosed.png);
            background-position: center center;
            background-size: 100% 100%;
            background-repeat: no-repeat;
        }

        /*紅包*/
        .redpack {
            position:absolute;
            width:100%;
            height:100%;
            left:0;
            top:0;
            display:flex;
            display:-webkit-flex;
            flex-direction:row;
            justify-content: center;
            align-items: center;
            background-color: rgba(0,0,0,.8);
            display:none;
            z-index: 9999;
        }
        /*r-item == redpack-item*/
        .r-item {
            position:absolute;
            top:-100%;
            transition:.2s;
            height:60%;
            width:100%;
            /* background-image: url(./img/redpack_boot.gif); */
            /*background-image: url(./img/redpack_opened.png);*/
            background-position: center center;
            /* background-repeat: no-repeat; */
            background-size: 100% 100%;
            display:flex;
            display:-webkit-flex;
            flex-direction:column;
            justify-content: center;
            align-items: center;
        }
        /*領取到紅包后,顯示的文字*/
        .r-item .info-item {
            width:50%;
            height:20%;
            color:#fff;
            font-size:3rem;
            text-align:center;
            /*border:1px solid yellow;*/
            display:flex;
            display:-webkit-flex;
            flex-direction:row;
            justify-content: center;
            align-items: center;
            display:none;
        }
        /*四條邊界相味,用于關閉紅包窗口*/
        .r-side {
            position:absolute;
            /*border:1px solid yellow;*/
            display:none;
        }
        .r-side1 {
            height:25%;
            width:100%;
            left:0;
            top:0;
        }
        .r-side2 {
            height:25%;
            width:100%;
            left:0;
            bottom:0;
        }
        .r-side3 {
            height:100%;
            width:15%;
            left:0;
            top:0;
        }
        .r-side4 {
            height:100%;
            width:15%;
            right:0;
            top:0;
        }
    </style>
</head>
<body>
<div class="cont-box">
    <div id="weChatBody">
    </div>
</div>
<div class="input-box">
    <div class="i-box">
        <div class="b-item item1" id="weChatStyle">樣式</div>
        <div class="b-item item2 item-input" id="weChatInput"  contenteditable="true"></div>
        <div class="b-item item3" id="sendMessage">發(fā)送</div>
    </div>
    <div class="input-style">
        <div class="s-item active" data-color="#222"><i></i></div>
        <div class="s-item" data-color="#ff0002"><i></i></div>
        <div class="s-item" data-color="#fcff00"><i></i></div>
        <div class="s-item" data-color="#1eff00"><i></i></div>
        <div class="s-item" data-color="#096bff"><i></i></div>
        <div class="s-item" data-color="#ff00d5"><i></i></div>
    </div>
</div>
<!-- 紅包 -->
<div class="redpack">
    <div class="r-item">
        <div class="info-item"></div>
        <div class="info-item money-item"><p>¥2.00元</p></div>
    </div>
    <!-- 周圍的四個可以點擊使得紅包消失的條 -->
    <div class="r-side r-side1"></div>
    <div class="r-side r-side2"></div>
    <div class="r-side r-side3"></div>
    <div class="r-side r-side4"></div>
</div>
<input type="hidden" name="nickname" id="nickNameVal" value="{$user.user_name}">
</body>
<script type="text/javascript">

    // 工具函數
    function gObj(obj){
        return document.querySelector(obj);
    }

    function ajax(method, url, data, success)
    {
        var xhr = null;
        try {
            xhr = new XMLHttpRequest();
        } catch (e) {
            xhr = new ActiveXObject('Microsoft.XMLHTTP');
        }

        if (method == 'get' && data) {
            url += '?' + data;
        }

        xhr.open(method,url,true);
        if (method == 'get') {
            xhr.send();
        } else {
            xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
            xhr.send(data);
        }

        xhr.onload = function() {
            success && success(xhr.responseText);
        }
        xhr.onerror = function(){
            console.log('錯誤信息:' + xhr.status);
        }
    }
</script>
<!--<script src="/socket.io.js"></script>-->
<script type="text/javascript">
    // 聊天框的高度oBox_h
    // 輸入框對象 oInput
    // 用戶昵稱oNickname
    // 所有顏色樣式的對象aStyleColor
    var oBox_h = gObj('.cont-box').offsetHeight;
    var oInput = gObj('#weChatInput');
    var oSendBtn = gObj('#sendMessage');
    var oNickname = gObj('#nickNameVal').value;
    var aStylecolor = document.querySelectorAll('.input-style div');
    var oDatas = '';
    var re = /^[\s\n]*?$/i; // 判斷輸入的內容是否為空格拾积,回車,換行符
    // var ren = /[\n]
    var wStyleOff = false; // 樣式開關wStyleOff, 默認false丰涉,為關閉狀體
    var nowColor = '#222'; // 存儲當前的樣式顏色
    var aRedpack = document.querySelectorAll('.redpack .r-side'); // 獲取所有
    var aMoneyItem = document.querySelectorAll('.redpack .info-item'); // 獲取所有
    // 觸發(fā)發(fā)送按鈕
    oSendBtn.addEventListener(
            'touchstart', function(e){
                if(oInput.innerText == ''){
                    // 先判斷內容拓巧,如果無值,則點擊無效一死,如果為空格和回車肛度,則提示
                    return;
                }
                this.style.backgroundColor = '#f95833';
            }, false);
    oSendBtn.addEventListener(
            'touchend', function(e){
                // 先判斷內容,如果無值投慈,則點擊無效承耿,如果為空格和回車冠骄,則提示
                if(oInput.innerText == ''){
                    return;
                }
                if(re.test(oInput.innerText)){
                    alert('輸入內容必須為有效值');
                    return;
                }
                sendMessage();
            }, false);

    // 更換樣式的按鈕
    gObj('#weChatStyle').addEventListener(
            'touchend',function(){
                if(!wStyleOff){
                    gObj('.input-style').style.height = '15rem';
                    this.style.borderColor = '#aaa';
                    this.style.color = '#aaa';
                    wStyleOff = true;
                }else{
                    gObj('.input-style').style.height = '0';
                    this.style.borderColor = '#fb6846';
                    this.style.color = '#fb6846';
                    wStyleOff = false;
                }

            }, false);

    // 選擇顏色樣式
    for(var i=0; i<aStylecolor.length; i++){
        aStylecolor[i].addEventListener(
                'touchend', function(e){
                    for(var j=0; j<aStylecolor.length; j++){
                        aStylecolor[j].className = 's-item';
                    }
                    this.className = 's-item active';
                    nowColor = this.getAttribute('data-color');
                },
                false);

    }

    // 判斷輸入框的內容是否有值
    oInput.addEventListener(
            'input', function(e){
                if(oInput.innerText.length != ''){
                    oSendBtn.style.backgroundColor = '#fb6846';
                    oSendBtn.style.borderColor = '#fb6846';
                }else{
                    oSendBtn.style.backgroundColor = '#ddd';
                    oSendBtn.style.borderColor = '#ddd';
                }
            }, false);
    // 點擊聊天輸入框
    oInput.addEventListener(
            'touchend', function(e){
                gObj('.input-style').style.height = '0';
                gObj('#weChatStyle').style.borderColor = '#fb6846';
                gObj('#weChatStyle').style.color = '#fb6846';
                wStyleOff = false;
            }, false);


    /*************************************************************************************************************************************************************************************************************************************************************************/
    var ws = new WebSocket("ws://120.78.64.155:8081");
    ws.onopen = function(e) {
        console.log('已建立連接');
    }
    ws.onmessage = function(evt){
        console.log('接收到服務器返回信息:'+evt.data);
        var data = JSON.parse(evt.data);
        var oDiv = document.createElement('div');
        var oChatBody_h = gObj('#weChatBody').offsetHeight;
        var message = data.text;
        var color = data.color;
        var nickname = data.nickname;
        oDatas = '<span class="content" style="color:'+color+';">'+message+'</span>';
        oDiv.innerHTML = '<b class="nickname" style="color:#fb6846;"><span>'+nickname+'</span>:</b>'+oDatas;
        gObj('#weChatBody').appendChild(oDiv);
        if(oChatBody_h > oBox_h){
            gObj('.cont-box').scrollTop = oChatBody_h;
        }else{
            gObj('.cont-box').scrollTop = oBox_h;
        }
    }
    // 發(fā)送聊天內容的函數
    function sendMessage(){
        // oDiv為創(chuàng)建的div對象
        // oChatBody_h為聊天內容區(qū)的高度
        // var oDiv = document.createElement('div');
        // var oChatBody_h = gObj('#weChatBody').offsetHeight;
        // oDatas = '<span class="content" style="color:'+nowColor+';">'+oInput.innerText+'</span>';
        // oDiv.innerHTML = '<b class="nickname" style="color:#7590f3;"><span>'+oNickname+'</span>:</b>'+oDatas;
        // gObj('#weChatBody').appendChild(oDiv);
        // 去掉用戶輸入的回車,換行正則  /[\r\n]/g
        // socket.emit('message', { text: oInput.innerText.replace(/[\r\n]/g, '') ,color: nowColor,nickname:oNickname});
        var msg = oInput.innerText.replace(/[\r\n]/g, '');
        var sendInfo = {
            'text': msg,
            'color': nowColor,
            'nickname': oNickname,
        };
        sendInfo = JSON.stringify(sendInfo);
        ws.send(sendInfo);
        // 清空輸入框加袋,還原按鈕樣式
        oInput.innerText = '';
        oSendBtn.style.backgroundColor = '#ddd';
        oSendBtn.style.borderColor = '#ddd';
        // console.log(gObj('#weChatBody').offsetHeight);
        // 關閉滾動窗口的自動上滾
        // if(oChatBody_h > oBox_h){
        //  gObj('.cont-box').scrollTop = oChatBody_h;
        // }else{
        //  gObj('.cont-box').scrollTop = oBox_h;
        // }
    }
    /*************************************************************************************************************************************************************************************************************************************************************************/

</script>

</html>

彈幕系統(tǒng)

彈幕系統(tǒng)涵蓋了公司的抽獎系統(tǒng)凛辣,有些css沒有刪除,請各位看官自行移除一下职烧,當然不移除也不會有問題的扁誓。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>抽獎系統(tǒng)</title>
    <style type="text/css">
        html {
                font-size:62.5%;
                color:#222;    /**不建議使用純黑,會顯得呆板**/
            }
        /*抽獎引導頁面*/
        body,html {
            margin:0;
            padding:0;
            height:100%;
            width:100%;
        }
        /*載入字體*/
        @font-face {
          font-family: gPrize-font01;
          src:url(__STATIC__/css/font/gPrize-font01.ttf);
        }
        html {
            font-family: gPrize-font01;
                background-image: url(__STATIC__/img/boot_bg_static.png);
                background-position: 0 0;
                background-size: 100% 100%;
        }
        /*引導頁面*/
        .boot-page {
            height:100%;
            width:100%;
            display:flex;
            display:-webkit-flex;
            flex-direction:column;
            justify-content:center;
            align-items: center;
            /* background-color: #ffc3c3; */
            position:absolute;
            top:0;
            left:0;
        }
        .boot-page .item {
            height:150px;
            text-align:center;
            line-height: 170px;
            color:#fff;
            font-size:42px;
            font-weight:bold;
            text-shadow:5px 2px 6px #111;

            position:relative;
        }
        .boot-page .item:nth-of-type(1){
            width:auto;
        }
        .boot-page .item div {
            float:left;
            height:150px;
        }
        .boot-page .title{
            width:auto;
            margin-right:10px;
            font-size:10rem;
        }
        /* .boot-page .btn{
            width:150px;
            background-image: url(./img/gift_btn.png);
            background-size: 100% auto;
            background-repeat: no-repeat;
            background-position: center center;

        } */

        /*抽獎系統(tǒng)頁面--內容頁*/
        .content-page {
            height:100%;
            width:100%;
            display:flex;
            display:-webkit-flex;
            flex-direction:row;
            justify-content:space-between;
            align-items: stretch;
            /* background-color: #1a1f39; */
            background-image: url(__STATIC__/img/lottery_bg.png);
            background-position: 0 0;
            background-size: 100% 100%;
            overflow: hidden;
            position:absolute;
            top:0;
            left:0;
        }
        /* .main-item {
            position:relative;
            overflow-x:hidden;
        } */
        .main-item{
            width:100%;
            overflow:hidden;
        }
        .left-title {
            position:relative;
            height:auto;
            border-bottom:1px solid #ddd;
        }
        .title-level {
            height:60px;
            line-height: 90px;
            text-align:center;
            font-size:25px;
        }
        .left-detail {
            text-align:center;
            padding:0 10px;
            box-sizing: border-box;
        }
        .left-users {
            position: relative;
            box-sizing: border-box;
            z-index: 88;
        }
        .left-users p {
            padding: 9px 15px;
            display:flex;
            display:-webkit-flex;
            flex-direction:row;
            justify-content:center;
            align-items: center;
        }
        .left-users p span {
            display:inline-block;
        }
        .left-users .nickname {
            text-indent:30px;
            overflow: hidden;
            text-overflow:ellipsis;
            white-space: nowrap;
        }
        /*左邊右下角的貓*/
        .left-right-bottom {
            height:80px;
            width:80px;
            position:fixed;
            z-index: 1;
            right:82%;
            bottom:0;
        }
        .left-right-bottom img {
            height:100%;
            width:100%;
        }
        /*公開透明抽獎區(qū)域*/

        .main-item .wrap {
            padding:4.5rem;
            box-sizing: border-box;
            width:100%;
            height:100%;
            position:relative;
            display:flex;
            display:-webkit-flex;
            flex-direction:row;
            align-items: center;
            justify-content:space-around;
            flex-wrap: wrap;
            position:absolute;

            left:0;
            top:200%;
        }
        .main-item .wrap .title-name {
            text-align:center;
        }
        .main-item .wrap .item {

            position:relative;
            /* background-color:rgba(255,255,255,.3); */
            display:-webkit-flex;
            flex-direction:row;
            align-items: center;
            justify-content:space-between;
            text-align:center;
        }


        /*手機號碼格式*/
        .wrap .item div {
            /*border:1px solid blue;*/
            height:100%;
            /*line-height: 5rem;
            float:left;*/
            /*手機好字體大小*/
            font-size:2.7rem;
            display:flex;
            display:-webkit-flex;
            flex-direction:row;
            align-items: center;
            justify-content:space-between;
            color:yellow;
        }
        .wrap .item div p {
            width:100%;
        }
        .wrap .item .first {
            width:33%;
        }
        .wrap .item .center {
            width:25%;
            font-size:2rem;
        }
        .wrap .item .last {
            width:42%;
        }

        /*41<=num<=50*/
        .main-item .wrap-41-50 .item {
            width:19.2%;
            height:7.8%;
        }

        /*31<=num<=40*/
        .main-item .wrap-31-40 .item {
            width:19.2%;
            height:9.8%;
        }

        /*21<=num<=30*/
        .main-item .wrap-21-30 .item {
            width:19.2%;
            height:14%;
        }

        /*11<=num<=20*/
        .main-item .wrap-11-20 .item {
            width:23.8%;
            height:15%;
        }
        .main-item .wrap-11-20 div {
            font-size:3.3rem;
        }
        /*1<=num<=10*/
        .main-item .wrap-3-10 .item {
            width:30.8%;
            height:20%;
        }
        .main-item .wrap-3-10 div {
            font-size:5rem;

        }
        .main-item .wrap-3-10 {
            justify-content:space-around;
        }
        .wrap-3-10 .item .first {
            width:35%;
        }
        .wrap-3-10 .item .center {
            width:21%;
        }
        .wrap-3-10 .item .last {
            width:44%;
        }
        /*2<=num<=2*/
        .main-item .wrap-1-2 .item {
            width:42%;
            height:25%;
        }
        .main-item .wrap-1-2 div p{
            font-size:6.6rem;
        }
        .main-item .wrap-1-2 {
            justify-content:space-around;
        }

        /*中間星號字體大小 ---- 放最后*/
        .wrap .item .center {
            font-size:2rem;
        }
        .wrap-1-2 .item .center {
            font-size:4rem;
        }

        /*彈幕*/
        .barrage {
            position:absolute;
            left:0;
            top:0;
            width:100%;
            height:100%;
            z-index: 99999;
            overflow: hidden;
            transform-style:preserve-3d;
            -webkit-transform-style:preserve-3d;
        }
        .b-item {
            position:absolute;
            height:auto;
            width:800px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            padding:1.3rem 1.5rem;
            /* border-radius: 10rem; */
            font-size:5rem;
            /* background-color: rgba(0, 0, 0, .8); */
            top:90%;
            right:-900px;
            color:#fff;
        }

        /* <!-- 左上角的二維碼 --> */
        .boot-page .qr-code {
            width:15rem;
            height:15rem;
            background-image: url(__STATIC__/img/hanwen_year_qrcode.png);
            background-position: center center;
            background-size:100% 100%;
            background-repeat:no-repeat;
            position:relative;
        }
        .boot-page .qr-code p {
            position:absolute;
            font-size:1.9rem;
            padding:0;
            margin:0;
            height:2rem;
            line-height: 2rem;
            width:100%;
            left:0;
            bottom:-2.2rem;
        }

        /* logo區(qū)域 */
        .hanwen-logo {
            position:absolute;
            bottom:0;
            left:0;
            height:15rem;
            width:15rem;
            /* background-image: url(__STATIC__/img/hanwen_logo.png); */
            background-position: center center;
            background-size:100% 100%;
            background-repeat:no-repeat;
        }

        /* 彩蛋表情包 */
        #caidan {
            height:300px;
            width:300px;
            position:absolute;
            top:50%;
            left:50%;
            margin-top:-150px;
            margin-left:-150px;
            /* background-image:  */
            background-position: 0 0;
            background-size: 100% 100%;
        }
    </style>
</head>
<body>

    <!-- 彈幕 start-->
    <div class="barrage">
        <div class="b-item" style="display:none;"></div>
        <!-- <div class="b-item"></div> -->
    </div>
    <!-- 彈幕 end-->
    <div class="" id="caidan" style="position:absolute;z-index:999;">

    </div>
</body>
<!-- 彈幕script -->
<script type="text/javascript">
// 工具函數
    function gObj(obj){
        return document.querySelector(obj);
    }

    function ajax(method, url, data, success)
    {
        var xhr = null;
        try {
            xhr = new XMLHttpRequest();
        } catch (e) {
            xhr = new ActiveXObject('Microsoft.XMLHTTP');
        }

        if (method == 'get' && data) {
            url += '?' + data;
        }

        xhr.open(method,url,true);
        if (method == 'get') {
            xhr.send();
        } else {
            xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded');
            xhr.send(data);
        }

        xhr.onload = function() {
            success && success(xhr.responseText);
        }
        xhr.onerror = function(){
            console.log('錯誤信息:' + xhr.status);
        }
    }
    // var socket = io.connect('http://120.78.64.155:8081');
        // 計時器蚀之,計算某個時間段內的彈幕數量
        var ws = new WebSocket("ws://120.78.64.155:8081");
        ws.onopen = function(e) {
            // Check the protocol chosen by the server
            console.log('已建立連接');
        }
        var tm = 1;
        var topvlast = topv = 13;
        ws.onmessage = function(evt){
            console.log('接收到服務器返回信息:'+evt.data);
            var data = JSON.parse(evt.data);
            topv += 8

            if(topv > 65){
                topv = 21;
            }
            barrage(data, topv);
        }

        var timer_m_x = null;
        function barrage(obj, topv){
            var oDiv = document.createElement('div');
            // 字幕wraper對象
             var oBarrage = gObj('.barrage');
            // var oDiv = gObj('.barrage .b-item');

            oDiv.innerText = obj.nickname+':'+obj.text;
            oDiv.className = 'b-item';
            if(obj.color != '#222'){
                oDiv.style.color = obj.color;
            }
            oDiv.x = 0;
            oDiv.style.top = topv + '%';
            setTimeout(function(){
                oBarrage.appendChild(oDiv);
                oDiv.timer = setInterval(function(){

                    oDiv.x -= 1;
                    oDiv.style.transform = 'translateX('+oDiv.x+'px)';

                    if(-oDiv.x > oBarrage.offsetWidth+900){
                        clearInterval(oDiv.timer);
                        oBarrage.removeChild(oDiv);
                    }

                }, Math.random()*10);
            }, Math.random()*1000);
        }

</script>
</html>

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末蝗敢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子足删,更是在濱河造成了極大的恐慌寿谴,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件失受,死亡現(xiàn)場離奇詭異拭卿,居然都是意外死亡,警方通過查閱死者的電腦和手機贱纠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來响蕴,“玉大人谆焊,你說我怎么就攤上這事∑忠模” “怎么了辖试?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長劈狐。 經常有香客問我罐孝,道長,這世上最難降的妖魔是什么肥缔? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任莲兢,我火速辦了婚禮,結果婚禮上续膳,老公的妹妹穿的比我還像新娘改艇。我一直安慰自己,他們只是感情好坟岔,可當我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布谒兄。 她就那樣靜靜地躺著,像睡著了一般社付。 火紅的嫁衣襯著肌膚如雪承疲。 梳的紋絲不亂的頭發(fā)上邻耕,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音燕鸽,去河邊找鬼兄世。 笑死,一個胖子當著我的面吹牛绵咱,可吹牛的內容都是我干的碘饼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼悲伶,長吁一口氣:“原來是場噩夢啊……” “哼艾恼!你這毒婦竟也來了?” 一聲冷哼從身側響起麸锉,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤钠绍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后花沉,有當地人在樹林里發(fā)現(xiàn)了一具尸體柳爽,經...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年碱屁,在試婚紗的時候發(fā)現(xiàn)自己被綠了磷脯。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡娩脾,死狀恐怖赵誓,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情柿赊,我是刑警寧澤俩功,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站碰声,受9級特大地震影響诡蜓,放射性物質發(fā)生泄漏。R本人自食惡果不足惜胰挑,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一蔓罚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧洽腺,春花似錦脚粟、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至藕坯,卻和暖如春团南,著一層夾襖步出監(jiān)牢的瞬間噪沙,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工吐根, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留正歼,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓拷橘,卻偏偏與公主長得像局义,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子冗疮,可洞房花燭夜當晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內容