用swoole實現實時彈幕網站demo
阿新 • • 發佈:2018-12-14
最近一直在學swoole就老想著用它做點東西,之前有接觸過個一個jquery彈幕外掛,於是我便使用這個外掛結合swoole做了一個彈幕網站demo。 外掛github地址:https://github.com/chiruom/jquery.danmu.js 使用教程:地址裡都有介紹,這裡就不一一贅述了 官方提供了一個demo,前端頁面我就直接在官方demo的基礎上加上了websocket,頁面效果展示如下: 前端index.html程式碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>jQuery.danmu.js jQuery彈幕外掛</title> <style> body { font-family: "Microsoft YaHei" ! important; font-color:#222; } pre { line-height: 2em; font-family: "Microsoft YaHei" ! important; } h4 { line-height: 2em; } #danmuarea { position: relative; background: #222; width:800px; height: 445px; margin-left: auto; margin-right: auto; } .center { text-align: center; } .ctr { font-size: 1em; line-height: 2em; } </style> <!--官方demo裡沒有jquery.min.js 這裡 用的是百度的CDN公共庫--> <script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script> <script src="../dist/jquery.danmu.min.js"></script> </head> <body class="center"> Demo<br><br> <!--黑背景和彈幕區--> <div id="danmuarea"> <div id="danmu" > </div> </div> <!--控制區--> <div class="ctr" > <button type="button" onclick="resumer() ">彈幕開始/繼續</button> <button type="button" onclick="pauser()">彈幕暫停</button> 顯示彈幕:<input type='checkbox' checked='checked' id='ishide' value='is' onchange='changehide()'> 彈幕透明度: <input type="range" name="op" id="op" onchange="op()" value="100"> <br> 當前彈幕執行時間(秒):<span id="time"></span> 設定當前彈幕時間(秒): <input type="text" id="set_time" max=20 /> <button type="button" onclick="settime()">設定</button> <br> 發彈幕: <select name="color" id="color" > <option value="white">白色</option> <option value="red">紅色</option> <option value="green">綠色</option> <option value="blue">藍色</option> <option value="yellow">黃色</option> </select> <select name="size" id="text_size" > <option value="1">大文字</option> <option value="0">小文字</option> </select> <select name="position" id="position" > <option value="0">滾動</option> <option value="1">頂端</option> <option value="2">底端</option> </select> <input type="textarea" id="text" max=300 /> <button type="button" onclick="send()">傳送</button> </div> <script> var wsServer = 'ws://192.168.8.131:9502'; var websocket = new WebSocket(wsServer); websocket.onopen = function(evt){ console.log('連線成功'); $("#danmu").danmu('danmuResume'); } websocket.onmessage = function(evt){ console.log('接收資料:'+evt.data); var new_obj=eval('('+evt.data+')'); console.log(new_obj); $('#danmu').danmu("addDanmu",new_obj); } websocket.onclose = function(evt){ console.log("伺服器拒絕"); } websocket.onerror = function(evt,e){ console.log('錯誤:'+evt.data); } //初始化 $("#danmu").danmu({ left:0, top:0, height:"100%", width:"100%", speed:20000, opacity:1, font_size_small:16, font_size_big:24, top_botton_danmu_time:6000 }); //一個定時器,監視彈幕時間並更新到頁面上 function timedCount(){ $("#time").text($('#danmu').data("nowTime")); t=setTimeout("timedCount()",50) } timedCount(); function starter(){ $('#danmu').danmu('danmuStart'); } function pauser(){ $('#danmu').danmu('danmuPause'); } function resumer(){ $('#danmu').danmu('danmuResume'); } function stoper(){ $('#danmu').danmu('danmuStop'); } function getime(){ alert($('#danmu').data("nowTime")); } function getpaused(){ alert($('#danmu').data("paused")); } //傳送彈幕,使用了文件README.md第7節中推薦的方法 function send(){ var text = document.getElementById('text').value; var color = document.getElementById('color').value; var position = document.getElementById('position').value; var size =document.getElementById('text_size').value; var time = $('#danmu').data("nowTime")+2; var text_obj='{ "text":"'+text+'","color":"'+color+'","size":"'+size+'","position":"'+position+'","time":'+time; websocket.send(text_obj); document.getElementById('text').value=''; } //調整透明度函式 function op(){ var op=document.getElementById('op').value; $('#danmu').danmu("setOpacity",op/100); } //調隱藏 顯示 function changehide() { var op = document.getElementById('op').value; op = op / 100; if (document.getElementById("ishide").checked) { $("#danmu").danmu("setOpacity",1) } else { $("#danmu").danmu("setOpacity",0) } } //設定彈幕時間 function settime(){ var t=document.getElementById("set_time").value; t=parseInt(t) $('#danmu').danmu("setTime",t); } </script> </body> </html>
服務端index.php程式碼:
<?php //伺服器程式碼 //建立websocket 伺服器 $ws = new swoole_websocket_server("0.0.0.0",9502); // open $ws->on('open',function($ws,$request){ echo "新使用者 $request->fd 加入。\n"; $GLOBALS['fd'][$request->fd]['id'] = $request->fd;//設定使用者id }); //message $ws->on('message',function($ws,$request){ //傳送每一個客戶端 //這裡也可以遍歷$ws->connections,遍歷的元素為單個連線的fd foreach($GLOBALS['fd'] as $i){ if ($request->fd == $i['id']) { $ws->push($i['id'],$request->data.',"isnew":1}'); } else { $ws->push($i['id'],$request->data.'}'); } } }); //close $ws->on('close',function($ws,$request){ echo "客戶端{$request->fd} 斷開連線\n"; unset($GLOBALS['fd'][$request->fd]);//清除連線倉庫 }); $ws->start();
使用時服務端執行php index.php 然後瀏覽器訪問index.html即可 我這裡地址是 http://192.168.8.131/swoole-danmu/demo/index.html 當然上面的demo有一個問題,就是有新的使用者連線上或者重新整理頁面的話,無法看到之前的彈幕,這一點就很容易解決了,把彈幕儲存起來就行了,官方也給瞭解決方案,就是在新增彈幕之前先使用ajax非同步將彈幕存到資料庫中,每次重新整理頁面或者有新使用者連線上開啟頁面時先把資料庫裡的彈幕資料用ajax非同步訪問服務端取出來並新增到頁面中。 這裡我就不做演示了,官方文件以及demo裡都有詳細介紹