当前位置: 欣欣网 > 码农

基于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

协同画板实现效果