當前位置: 妍妍網 > 碼農

基於Websocket和Canvas實作多人協作即時共享白板

2024-06-19碼農

概述

本文主要基於 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

協同畫板實作效果