HTML + JS: 【网上找到弹幕代码】
<meta charset="utf-8"/>
<div class="container">
<div id="content" class="content">
<img src="./1.png"/>
</div>
<div class="content-opt">
<div id="content-text" class="content-text"></div>
<div class="content-input">
<input id="text" type="text">
<button id="send">发送</button>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<style>
* {
box-sizing: border-box;
outline: none;
}
p {
margin: .5em;
word-break: break-all;
}
.container {
position: relative;
width: 700px;
height: 500px;
margin: auto;
padding-right: 200px;
}
.content {
width: 100%;
height: 100%;
border: 1px solid #ccc;
}
.content-opt {
position: absolute;
top: 0;
right: 0;
width: 200px;
height: 100%;
}
.content-text {
height: calc(100% - 30px);
margin-bottom: 30px;
border: 1px solid #ccc;
overflow: auto;
}
.content-input {
position: absolute;
bottom: 0;
width: 100%;
height: 30px;
border: 1px solid #ccc;
}
.content-input input {
width: 70%;
padding: 2px;
border-radius: 5px;
}
.content-input button {
padding: 3px 10px;
border: none;
border-radius: 5px;
background: rgb(90, 154, 214);
}
</style>
<script>
(function() {
class Barrage {
constructor(id) {
this.domList = [];
this.dom = document.querySelector('#' + id);
if (this.dom.style.position == '' || this.dom.style.position == 'static') {
this.dom.style.position = 'relative';
}
this.dom.style.overflow = 'hidden';
let rect = this.dom.getBoundingClientRect();
this.domWidth = rect.right - rect.left;
this.domHeight = rect.bottom - rect.top;
}
shoot(text) {
let div = document.createElement('div');
div.style.position = 'absolute';
div.style.left = this.domWidth + 'px';
div.style.top = (this.domHeight - 20) * +Math.random().toFixed(2) + 'px';
div.style.whiteSpace = 'nowrap';
div.style.color = '#' + Math.floor(Math.random() * 256).toString(10);
div.innerHTML = text;
this.dom.appendChild(div);
// $(this).append(div);
let roll = (timer) =>{
let now = +new Date();
roll.last = roll.last || now;
roll.timer = roll.timer || timer;
let left = div.offsetLeft;
let rect = div.getBoundingClientRect();
if (left < (rect.left - rect.right)) {
this.dom.removeChild(div);
} else {
if (now - roll.last >= roll.timer) {
roll.last = now;
left -= 3;
div.style.left = left + 'px';
}
requestAnimationFrame(roll);
}
}
roll(50 * +Math.random().toFixed(2));
}
}
let barage = new Barrage('content');
function appendList(text) {
// let p = document.createElement('p');
// p.innerText = text;
// document.querySelector('#content-text').appendChild(p);
$('#content-text').append( '<p>'+text+'</p>');
}
document.querySelector('#send').onclick = () =>{
let text = document.querySelector('#text').value;
// alert(text);
// 弹幕信息推送到服务端
var json = '{"type":"danmu","room_id":'+room_id+',"content":"'+text+'"}';
websocket.send( json );
// barage.shoot(text);
//
// appendList(text);
};
const textList = [
];
textList.forEach((s) =>{
barage.shoot(s);
appendList(s);
});
var room_id = 1;
var wsServer = 'ws://**.**.**.**:9501';
var websocket = new WebSocket(wsServer);
var user_name = '用户'+ Math.ceil(Math.random()*10000);
websocket.onopen = function (evt) {
console.log("Connected to WebSocket server.");
var json = '{"type":"connect","user_name" : "'+user_name+'","room_id":'+room_id+' }';
console.log( '房间的数据:' + json );
websocket.send( json );
};
websocket.onclose = function (evt) {
console.log("Disconnected");
};
websocket.onmessage = function (evt) {
console.log('Retrieved data from server: ' + evt.data);
var obj = JSON.parse( evt.data );
if( obj.type == 'danmu' ){
var text = obj.content;
barage.shoot(text);
appendList(text);
}
};
websocket.onerror = function (evt, e) {
console.log('Error occured: ' + evt.data);
};
})();
</script>
php代码:
<?php
/**
* Created by PhpStorm.
* User: LiKang
* Date: 2019/8/26
* Time: 14:16
*/
//创建websocket服务器对象,监听0.0.0.0:9501端口
$ws = new swoole_websocket_server( "0.0.0.0", 9501 );
//监听WebSocket连接打开事件
$ws->on('open', function ($ws, $request) {
$ws->push( $request->fd, json_encode([]) );
});
//监听WebSocket消息事件
$ws->on('message', function ($ws, $frame) {
$data = json_decode( $frame -> data , true );
$danmu_obj = new DanMu();
$data['fd'] = $frame -> fd;
if( $data['type'] == 'connect' ){
$data = $danmu_obj ->Connect( $data );
$return = [
'type' => 'join',
'data' => $data
];
$ws->push($frame->fd, json_encode( $return ) );
}elseif( $data['type'] == 'danmu' ){
# 接受用户的弹幕信息,并且通知到房间的所有人
$room_user = $danmu_obj -> getRoomUser( $data['room_id'] );
foreach( $room_user as $k => $v )
{
if( $v['fd'] == $frame ->fd ){
$user_name = $v['user_name'];
break;
}
}
$message_data = [
'content' => '<span class="name">'.$user_name
.'</span> : '.$data['content'],
'type'=>'danmu'
];
foreach( $room_user as $k => $v ){
var_dump($v);
$ws -> push( $v['fd'] , json_encode( $message_data ) );
}
}
// echo "Message: {$frame->data}\n";
});
//监听WebSocket连接关闭事件
$ws->on('close', function ($ws, $fd) {
echo "client-{$fd} is closed\n";
});
$ws->start();
class DanMu{
public $redis_obj;
public function __construct()
{
$this->redis_obj = new Swoole\Coroutine\Redis();
$this->redis_obj->connect('127.0.0.1', 6379);
}
/**
* 用户进入房间,加入对应的房间
*/
public function Connect( $data )
{
$this_join = $this -> joinRoom( $data , $data['room_id'] );
return $this_join;
}
/**
* @param $data
* @param $room_id
*/
private function joinRoom( $data , $room_id )
{
$key = 'Room:Room_' . $room_id ;
$json = $this -> redis_obj -> get( $key );
$room_data = json_decode( $json ,true );
$this_join = [
[
'user_name' => $data['user_name'],
'room_id' => $data['room_id'],
'fd' => $data['fd']
]
];
$all = array_merge( (array) $room_data , $this_join );
$this -> redis_obj -> set( $key , json_encode($all) );
return $this_join;
}
public function getRoomUser( $room_id ){
$key = 'Room:Room_' . $room_id ;
$json = $this -> redis_obj -> get( $key );
$room_data = json_decode( $json ,true );
return $room_data;
}
}