在 Web 开发中,实时交互和协作是非常常见的需求,例如在线聊天、共享编辑、多人游戏等场景。而实现实时交互和协作的技术之一就是 Socket.io。Socket.io 是一个基于 Node.js 的实时的双向通信库,可以在客户端和服务器之间建立并维护双向通信通道。
在本文中,我们将介绍如何使用 Socket.io 实现多人实时协作的场景,并提供示例代码。
安装和使用 Socket.io
首先,我们需要安装 Socket.io。可以在项目中使用 npm 安装它:
npm install socket.io
在 Node.js 中,我们需要创建一个 Socket.io 服务器并监听它:
const server = require('http').createServer(); const io = require('socket.io')(server); io.on('connection', (socket) => { console.log('a user connected'); });
上面代码创建了一个 HTTP 服务器,并初始化了一个 Socket.io 实例。在连接建立时,服务器会打印一条连接信息。
客户端需要引入 Socket.io 客户端脚本,并连接 Socket.io 服务器:
<script src="/socket.io/socket.io.js"></script> <script> const socket = io(); </script>
上面代码中,/socket.io/socket.io.js
是 Socket.io 客户端脚本的 URL。连接成功后,客户端就可以向服务器发送事件,也可以接收从服务器发送过来的事件。
多人实时协作示例
下面我们来实现一个多人实时协作的示例。该示例是一个共享画板,多个用户可以在同一个画布上画图,并实时同步画布状态。
服务器端实现
这是服务器端的实现,它包含了两个事件:addLine
和 clear
。
// javascriptcn.com 代码示例 const server = require('http').createServer(); const io = require('socket.io')(server); const lines = []; io.on('connection', (socket) => { console.log('a user connected'); // 发送已有的画布状态给新加入的用户 socket.emit('load', lines); socket.on('addLine', (line) => { lines.push(line); io.emit('line', line); }); socket.on('clear', () => { lines.length = 0; io.emit('clear'); }); }); server.listen(3000);
代码解释:
lines
:保存画布状态的数组。load
事件:当有新用户加入时,将已有的画布状态发送给新加入的用户。addLine
事件:当某个用户在画布上画线时,向其他用户广播该线条的消息。clear
事件:当用户请求清空画布时,向所有用户广播清空画布消息。
客户端实现
下面是客户端的实现。该示例使用了 HTML5 的 Canvas 元素进行绘图。
// javascriptcn.com 代码示例 <html> <head> <style> #canvas { border: 1px solid #ccc; } </style> </head> <body> <canvas id="canvas"></canvas> <script src="/socket.io/socket.io.js"></script> <script> const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); const socket = io(); // 画笔颜色和宽度 let color = 'black'; let lineWidth = 2; // 鼠标按下时绘图 let isMouseDown = false; let lastX = 0; let lastY = 0; canvas.addEventListener('mousedown', (e) => { isMouseDown = true; lastX = e.pageX - canvas.offsetLeft; lastY = e.pageY - canvas.offsetTop; }); canvas.addEventListener('mousemove', (e) => { if (!isMouseDown) { return; } const x = e.pageX - canvas.offsetLeft; const y = e.pageY - canvas.offsetTop; const line = { color, lineWidth, from: { x: lastX, y: lastY }, to: { x, y } }; addLine(line); lastX = x; lastY = y; }); // 鼠标松开停止绘图 canvas.addEventListener('mouseup', () => { isMouseDown = false; }); // 广播新增线条事件 function addLine(line) { ctx.strokeStyle = line.color; ctx.lineWidth = line.lineWidth; ctx.beginPath(); ctx.moveTo(line.from.x, line.from.y); ctx.lineTo(line.to.x, line.to.y); ctx.stroke(); socket.emit('addLine', line); } // 接收其他用户画的线条并绘图 socket.on('line', (line) => { addLine(line); }); // 清空画布 document.getElementById('clear').addEventListener('click', () => { ctx.clearRect(0, 0, canvas.width, canvas.height); socket.emit('clear'); }); // 接收广播清空画布事件并清空画布 socket.on('clear', () => { ctx.clearRect(0, 0, canvas.width, canvas.height); }); // 接收已有的画布状态 socket.on('load', (lines) => { lines.forEach(addLine); }); </script> </body> </html>
代码解释:
color
和lineWidth
:画笔颜色和宽度。isMouseDown
:标记鼠标是否按下。lastX
和lastY
:记录上次绘图结束点的坐标。- 鼠标按下时保存当前位置为
lastX
和lastY
。 - 鼠标移动时计算新的点坐标,并使用
addLine
函数画出线条,并通过 Socket.io 将该线条发送给服务器。 - 鼠标松开时将
isMouseDown
设为false
。 addLine
函数:使用 Canvas 画出一条线条,并发送addLine
事件给服务器。- 接收到
line
事件时,使用addLine
函数画出收到的线条。 clear
按钮点击时将画布清空,并发送clear
事件给服务器。- 接收到
clear
事件时,清空画布。
总结
通过本文的介绍和示例代码,读者可以了解到 Socket.io 的一些基本用法和如何在 Node.js 中使用 Socket.io 实现多人实时协作,同时也可以根据示例代码构建更复杂的实时交互和协作的应用。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/653f7fad7d4982a6eb910792