概述
本文主要基於 Websocket、Canvas、Webman、HTML5 CSS 等技術實作一個共享白板原型,支持在多個桌面瀏覽器之間共享一個無限大小、任意縮放的多人即時協作白板,並即時同步繪畫、塗鴉。透過 Canvas 渲染畫板、產生塗鴉數據,然後透過Websocket實作客戶端與伺服器的雙向通訊,並在多個裝置之間即時同步塗鴉數據。
協同畫板實作
使用workerman作為Websocket訊息訂閱釋出伺服器
安裝think-template
composer安裝
composer require topthink/think-template
修改配置
config/view.php
為
<?php
usesupport\view\ThinkPHP;
return [
'handler' => ThinkPHP:: class,
];
HTTP服務
新建
app/controller/DemoController.php
控制器
<?php
/**
* @desc Demo.php 描述資訊
* @author Tinywan(ShaoBo Wan)
* @date 2024/6/16 20:14
*/
declare(strict_types=1);
namespaceapp\controller;
usesupport\Request;
usesupport\Response;
classDemoController
{
/**
* @desc 實戰構建多人互動畫板
* @param Request $request
* @return Response
* @author Tinywan(ShaoBo Wan)
*/
publicfunctioncanvas(Request $request): Response
{
return view('demo/canvas');
}
}
檔
app/view/demo/canvas.html
如下
<!DOCTYPE html>
<htmllang="en">
<head>
<metacharset="UTF-8">
<title>開源技術小棧 WebSocket+Canvas: 實戰構建多人互動畫板</title>
</head>
<body>
<canvasid="canvas"height="600"width="600" style="border:1px solid #000000;">你的瀏覽器不支持canvas,請升級瀏覽器</canvas>
<scriptsrc="/static/js/index.js"></script>
</body>
</html>
/static/js/index.js
檔
var el = document.getElementById('canvas');
el.width = document.body.clientWidth;
el.height = document.body.clientHeight;
var ctx = el.getContext('2d');
var isDrawing;
var point = {};
ctx.stroke style = '#fffff';
var ws = new WebSocket('ws://192.168.13.168:8788');
console.log(ws)
// 當連線成功後,再進行繪畫操作,以免數據遺失
ws.onopen = function () {
el.onmousedown = function (e) {
isDrawing = true;
ctx.moveTo(e.clientX,e.clientY);
sendPoint(e,1);
}
el.onmousemove = function (e) {
if(isDrawing){
ctx.lineTo(e.clientX,e.clientY);
ctx.stroke();
sendPoint(e,2);
}
}
el.onmouseup = function (e) {
isDrawing = false;
}
}
ws.onmessage = function (e) {
var data = JSON.parse(e.data);
if(data.type == 1){
ctx.moveTo(data.x,data.y);
}elseif(data.type == 2){
ctx.lineTo(data.x,data.y);
ctx.stroke();
}
}
functionsendPoint(e,type) {
point = {
type:type,
x:e.clientX,
y:e.clientY,
}
ws.send(JSON.stringify(point));
}
Websocket服務
這裏透過webman自訂行程實作。在webman中你可以像workerman那樣自訂監聽或者行程。
新建
process/CanvasWebsocket.php
<?php
/**
* @desc CanvasWebsocket.php
* @author Tinywan(ShaoBo Wan)
* @date 2024/6/18 9:18
*/
declare(strict_types=1);
namespaceprocess;
useWorkerman\Connection\TcpConnection;
classCanvasWebsocket
{
publicfunctiononConnect(TcpConnection $connection)
{
echo"onConnect\n";
}
publicfunctiononWebSocketConnect(TcpConnection $connection, $http_buffer)
{
echo"onWebSocketConnect\n";
}
publicfunctiononMessage(TcpConnection $connection, $data)
{
foreach ($connection->worker->connections as $_connection) {
if($connection != $_connection){
$_connection->send($data);
}
}
}
publicfunctiononClose(TcpConnection $connection)
{
echo"onClose\n";
}
}
在
config/process.php
中添加如下配置
return [
// ... 其它行程配置省略 ...
// canvas_websocket為行程名稱
'canvas_websocket' => [
// 這裏指定行程類,就是上面定義的Pusher類
'handler' => \process\CanvasWebsocket:: class,
'listen' => 'websocket://0.0.0.0:8788',
'count' => 1,
],
];
啟動webman