# 利用 websocket 实现简单弹幕

# 1、前言

这里会一步一步实现一个弹幕系统,依赖上一篇的内容,建议先查看上一篇再来查看此篇。

# 2、先看个简单例子

bullet.html

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta charset="utf-8">
    <title>斗鱼弹幕</title>
    <style>
        html, body {
            font-size: 10px;
            overflow: hidden;
            margin: 0;
            padding: 0;
        }
        #box {
            width: 100%;
            height: 100%;
        }
        #dm {
            width: 100%;
            height: 90vh;
            background: #E8F1F5;
        }
        #dm span {
            width: auto;
            height: 3rem;
            font-size: 2rem;
            line-height: 2rem;
            position: absolute;
            white-space: nowrap;
        }
        #idDom {
            width: 100%;
            height: 10vh;
            background: #666;
            position: absolute;
            bottom: 0;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        #content {
            width: 50rem;
            height: 10vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }
        .title {
            font-size: 2.2px rein;
            color: #fff;
            line-height: #ccc;
        }
        .text {
            width: 30rem;
            height: 2.5rem;
            border: none;
            border-radius: .5rem;
            font-size: 1.4rem;
            margin: 0 .5rem;
            padding: 0 1rem;
        }
        .btn {
            width: 6rem;
            height: 3rem;
            border: none;
            background: red;
            color: #fff;
        }
    </style>
</head>
<body>
<div class="box" id="box">
    <div id="dm"></div>
    <div class="idDom" id="idDom">
        <div id="content">
            <p class="title">吐槽:</p>
            <input type="text" class="text" id="text" placeholder="请输入你想说的话"/>
            <button type="button" class="btn" id="btn">发射!</button>
        </div>
    </div>
</div>
<script langugae="javascript">
    var timer;
    var btn = document.getElementById('btn');
    btn.onclick = function () {
        addBarrage();
    }
    document.onkeydown = function (evt) {
        var event = evt || window.event;
        if (event.keyCode == 13) {
            addBarrage();
        }
    }
    var colors = ['#2C3E50', '#FF0000', '#1E87F0', '#7AC84B', '#FF7F00', '#9B39F4', '#FF69B4'];// 弹幕颜色库
    function addBarrage() {
        clearInterval(timer);
        var text = document.getElementById('text').value;
        document.getElementById('text').value = "";
        var index = parseInt(Math.random() * colors.length); // 随机弹幕颜色
        var screenW = window.innerWidth;
        var screenH = dm.offsetHeight;
        var max = Math.floor(screenH / 40);
        var height = 10 + 40 * (parseInt(Math.random() * (max + 1)) - 1);
        var span = document.createElement('span');
        span.style.left = screenW + 'px';
        span.style.top = height + 'px';
        span.style.color = colors[index];
        span.innerHTML = text;
        var dmDom = document.getElementById('dm');
        dmDom.appendChild(span);
        timer = setInterval(move, 10);
    }
    function move() {
        var arr = [];
        var oSpan = document.getElementsByTagName('span');
        for (var i = 0; i < oSpan.length; i++) {
            arr.push(oSpan[i].offsetLeft);
            arr[i] -= 2;
            oSpan[i].style.left = arr[i] + 'px';
            if (arr[i] < -oSpan[i].offsetWidth) {
                var dmDom = document.getElementById('dm');
                dmDom.removeChild(dmDom.childNodes[0]);
            }
        }
    }
</script>
</body>
</html>

直接运行这个 html 页面你就能看到一个由 js 实现的弹幕,但是这个弹幕没有通信的作用。

# 3、部署 websocket 服务

上一篇编写的 websocket 服务,现在我们把他部署到服务器上,先打包然后再服务器上直接用 jar 运行,部署这一块自行解决,或者寻找百度。
如果不部署的话,就本地启用,访问的时候使用 http://loaclhost:8080/dreamlandWs 也行。 或者我提供一个线上的 websocket 服务:https://ws.yypdreamland.cn
前提你的服务也得是 https 的才能正常连接。

# 4、编写前端程序

接下来的可能就比较难了

# 1、准备好一个视频项目

这一步可能你需要花点心思,这里给一个图片示例:可以参考项目地址:https://yypdreamland.cn

红框中是我们需要绑定方法的

# 2、方法绑定

以下为示例,根据你项目中自己使用的前端框架自行绑定方法

方法体:

function openBullet() {
    layer.prompt({title: '请输入你的名字'}, function (value, index, elem) {
        if (value != null && value !== "" && value !== undefined) {
            userId = value;
            $("#open_bullet").hide();
            $("#close_bullet").show();
            // 连接 socket -- 当前的视频 id
            // console.log(urlResult[3])
            connect(urlResult[3]);
        }
        layer.close(index);
    })
}
function closeBullet() {
    // 断开 socket -- 当前的视频 id
    $("#close_bullet").hide();
    $("#open_bullet").show();
    disconnect();
}
function sendBullet() {
    // 发送弹幕
    stompClient.send("/dreamlandBullet/bullet", {}, JSON.stringify({
        'bullet': $("#bulletMsg").val(),
        'videoId': urlResult[3],
        'user': userId
    }));
}

对应的 app.js 修改和新增

function connect(videoId) {
    var socket = new SockJS('https://ws.yypdreamland.cn/dreamlandWs');
    stompClient = Stomp.over(socket);
    stompClient.connect({}, function (frame) {
        setConnected(true);
        console.log('Connected: ' + frame);
        stompClient.subscribe('/user/' + videoId + '/bullet', function (bullet) {
            // showGreeting(bullet.body);
            handleBullet(bullet.body);
        });
    });
}
function handleBullet(message) {
    // 处理播放弹幕
    var msg = JSON.parse(message);
    addBarrage(msg);
}
// 放弹幕
var timer;
var colors = ['#2C3E50', '#FF0000', '#1E87F0', '#7AC84B', '#FF7F00', '#9B39F4', '#FF69B4'];// 弹幕颜色库
function addBarrage(msg) {
    clearInterval(timer);
    var text = "";
    if (msg.user == userId) {
        text = "我:" + msg.message
    } else {
        text = msg.user + ":" + msg.message
    }
    var index = parseInt(Math.random() * colors.length); // 随机弹幕颜色
    var dmDom = document.getElementById('screen');
    var screenW = dmDom.offsetWidth;
    var screenH = dmDom.offsetHeight;
    var max = Math.floor(screenH / 40);
    var height = 10 + 40 * (parseInt(Math.random() * (max + 1)) - 1);
    var span = document.createElement('span');
    span.style.left = screenW + 'px';
    span.style.top = height + 'px';
    span.style.color = colors[index];
    span.innerHTML = text;
    span.setAttribute("bullet","yes")
    dmDom.appendChild(span);
    timer = setInterval(move, 10);
}
function move() {
    var arr = [];
    var oSpan = document.getElementById("screen").children;
    for (var i = 0; i < oSpan.length; i++) {
        arr.push(oSpan[i].offsetLeft);
        arr[i] -= 1;
        oSpan[i].style.left = arr[i] + 'px';
        if (arr[i] < -oSpan[i].offsetWidth) {
            var dmDom = document.getElementById('screen');
            dmDom.removeChild(dmDom.childNodes[0]);
        }
    }
}

以上如有不明白的地方可以发送邮件至我的邮箱:im.yyp@foxmail.com ;

# 3、效果展示

操作步骤:先打开弹幕,然后输入自己的名字(没有登录系统),然后就可以发送弹幕了。




以上为全部内容,多谢查阅!