Node.js + Socket.io 实现多人协作白板

阅读时长 14 分钟读完

在前端领域中,有很多需要多人协作的场景,比如设计师需要和开发工程师一起讨论和修改设计稿、团队需要协作完成前端代码等等。这时候使用一个多人协作白板就非常方便了。

本文将介绍如何使用 Node.js 和 Socket.io 实现一个多人协作白板,使得多人可以在同一画布上进行实时协作,并且能够看到彼此所做的修改。

准备工作

在开始之前,需要先准备好以下环境和工具:

  • Node.js 环境(包括 npm 包管理器)
  • 一个文本编辑器
  • 浏览器(推荐使用 Chrome 浏览器)

创建项目

首先,打开命令行或终端窗口,进入到你的项目目录中,并执行以下命令来创建一个新的 Node.js 项目:

执行完毕后,你会得到一个 package.json 文件,其中包含了项目的一些基本信息和依赖项。

接下来,在项目根目录下创建一个名为 index.js 的文件,用于编写我们的主要代码。

安装依赖项

在编写代码之前,我们需要安装一些所需的依赖项。打开命令行或终端窗口,进入到项目目录中,并执行以下命令:

这里我们安装了两个包:

  • express:一个流行的 Node.js web 框架,用于搭建服务器。
  • socket.io:一个实时通信库,用于实现多人协作。

编写代码

服务器端代码

打开 index.js 文件,首先我们需要引入所需的模块:

然后,我们需要创建一个 express 应用实例,并将其与一个 http 服务器绑定:

接下来,我们需要告诉 express 去哪个文件夹下面查找静态文件。我们可以通过下面的代码来实现:

这样,我们就可以在 public 文件夹下面存放静态文件了。

然后,我们需要绑定一个 socket.io 服务器到我们的 http 服务器上,并监听连接事件:

以上代码中,我们使用 socketIo(server) 方法将 socket.io 服务器绑定到 http 服务器上,并返回一个 io 对象,代表服务器实例。

然后,在 connection 事件中,我们通过回调函数拿到了一个 socket 对象,这个对象代表了一个连接到服务器的客户端。

现在,我们已经完成了服务器端的基本代码。接下来,我们需要编写一些和绘图相关的事件。

创建和加入房间

首先,我们需要添加一个事件让用户能够创建新的房间或加入已有的房间。我们可以通过下面的代码实现:

-- -------------------- ---- -------
--- ----- - ---

----------------------- ------ -- -
  ------------------
  ----------- - -
    ------ ------------
    --------- --
  --
---

--------------------- ------ -- -
  -- -------------- -
    -------
  -

  ------------------
  ----------------------------------
---

以上代码中,我们维护了一个包含所有房间信息的对象 rooms。当用户调用 createRoom 事件时,我们通过 socket.join(room) 让该客户端加入该房间,并将这个房间信息存入 rooms 对象中。当用户调用 joinRoom 事件时,我们首先检查该房间是否存在,如果存在,就让该客户端加入该房间。

绘图相关事件

接下来,我们需要实现和绘图相关的事件,包括 startDrawing(开始绘图)、continueDrawing(继续绘图)、stopDrawing(停止绘图)、undo(撤消操作)等。下面是这些事件的具体实现代码:

-- -------------------- ---- -------
------------------------- ------ ----- -- -
  -- -------------- -
    -------
  -

  ---------------------------
    ------- ----------
    ----- ------
  ---

  ------------------------------------ ---------- ------
---

---------------------------- ------ ----- -- -
  -- -------------- -
    -------
  -

  ----- -------- - ------------
  ----- ------- - ------------------------------------------ - ---

  -- --------------- --- ---------- -
    ------------------------
  -

  --------------------------------------- ---------- ------
---

------------------------ ------ ----- -- -
  -- -------------- -
    -------
  -

  ----- -------- - ------------
  ----- ------- - ------------------------------------------ - ---

  -- --------------- --- ---------- -
    ------------------------
  -

  ----------------------------------- ---------- ------
---

----------------- ------ -- -
  -- -------------- -
    -------
  -

  ----- -------- - ------------
  ----- -------- - ------------------
  ----- ----------- - ------------------------ - ---

  -- ------------------- --- ---------- -
    -------
  -

  -- ------------------------ - -- -
    -----------------------
    -----------------------------
  - ---- -
    ------------------------
    ------------------------------
  -
---

以上代码中,我们首先在 startDrawing 事件中将该用户开始绘图的数据存入 rooms 对象中,然后通过 socket.to(room).emit() 方法将消息广播给房间内其他成员。在 continueDrawingstopDrawing 事件中,我们需要找到该用户上一次绘图信息,然后判断是否应该将当前操作的数据加入到上一次绘图信息中。在 undo 事件中,我们需要找到该用户最后一次绘图信息,然后进行撤销操作或者删除整个绘图信息。

客户端代码

现在,我们已经完成了服务器端的相关代码。接下来,我们需要在客户端实现绘图并能够和服务端通信。首先,我们需要在 public 文件夹下创建一个 HTML 文件并添加相关代码:

-- -------------------- ---- -------
--------- -----
------
------
  ----- ----------------
  -----------------
  ----- ---------------- --------------------------------------------------------------------------------
  -------
    ----------- -
      ----------------- ------
      ------ -----
      ------- ------
    -
  --------
-------
------
  ---- ------------------
    ---- ------------
      ---- -----------------
        ---- ----------------------
      ------
      ---- -----------------
        -----------
        ---- -----------------
      ------
    ------
  ------

  ------- ---------------------------------------
  --------
    ----- ------ - -----

    ----- ---------- - --------------------------------------
    ----- ------- - ----------------------------

    --- ------- - ------

    ---------------------------------------- ------- -- -
      ------- - -----
      ----- ------- - --------------
      ----- ------- - --------------
      ----- - ----- --- - - -----------------------------------
      ----- - - ------- - -----
      ----- - - ------- - ----

      --------------------------- ----- - -- - ---
      ------- ---
    ---

    ---------------------------------------- ------- -- -
      -- ---------- -
        -------
      -

      ----- ------- - --------------
      ----- ------- - --------------
      ----- - ----- --- - - -----------------------------------
      ----- - - ------- - -----
      ----- - - ------- - ----

      ------------------------------ ----- - -- - ---
      ------- ---
    ---

    -------------------------------------- -- -- -
      ------- - ------
      -------------------------- ------
    ---

    ------------------------- -------- ----- -- -
      ------------ --------
    ---

    ---------------------------- -------- ----- -- -
      ------------ --------
    ---

    ------------------------ -------- ----- -- -
      -- -- -------
    ---

    ----- ---- - --- -- -- -
      ------------------- - --------
      ----------------- - --
      --------------- - --------

      -- ---------- -
        --------------------
        ----------------- ---
      - ---- -
        ----------------- ---
        -----------------
      -
    --

    ----- -------------- - ---------------------------------

    ------------------ ------ -- -
      ------------------------ - ---

      --- ---- ---- -- ----- -
        ----- ------ - ---------------------------------
        ---------------- - ---- -------------
        ---------------- - --- ------- --------------------------- ----
        -------------------------------- -- -- -
          ---- - -----
          ----------------------- ------

          ------------------------ - --------
          ---------------------------- - -------
        ---

        -----------------------------------
      -
    ---

    ------------------ -- -- -
      -------------------- -- ----------------- -------------------
    ---

    --- ---- - ---

    ----- ------- -
      ---- - ------------------- ----
    -

    ------------------------- ------
    ------------------ ------ -- -
      ------------------------ - ---

      --- ---- ---- -- ----- -
        ----- ------ - ---------------------------------
        ---------------- - ---- -------------
        ---------------- - --- ------- --------------------------- ----
        -------------------------------- -- -- -
          ---- - -----
          ----------------------- ------

          ------------------------ - --------
          ---------------------------- - -------
        ---

        -----------------------------------
      -
    ---
  ---------
-------
-------

以上代码中,我们首先引入了 socket.io 客户端库,然后创建了一个 socket 对象,表示到服务器的连接。

然后,我们获取了白板元素,并添加了鼠标事件监听器来实现绘图。当用户开始绘图时,我们通过 socket.emit('startDrawing', room, { x, y }) 发送消息到服务器。当用户继续绘图时,我们通过 socket.emit('continueDrawing', room, { x, y }) 发送消息给服务器。当用户停止绘图时,我们通过 socket.emit('stopDrawing', room) 发送停止事件给服务器。

在收到其他用户发送的 startDrawingcontinueDrawing 事件时,我们通过 draw(x, y) 方法进行绘图。当收到 stopDrawing 事件时,我们不做任何操作。

在页面加载时,我们需要让用户输入一个房间名,并调用 createRoom 事件来创建该房间。然后,我们通过 rooms 事件监听器来更新房间列表。

启动服务器

最后,我们需要在命令行或终端窗口中运行以下命令,启动服务器:

然后,在浏览器中打开 http://localhost:3000,就可以看到多人协作白板的运行效果了。

总结

通过本文的介绍,我们了解了如何使用 Node.js 和 Socket.io 实现多人协作白板,并编写了相应的代码。通过这个例子,我们可以更好地学习实时通信相关技术,以及如何在 Node.js 环境中搭建一个 web 服务器。希望本文能对你在前端开发中使用 Node.js 和 Socket.io 实现类似实时协作功能的项目有所帮助。

来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/646c4457968c7c53b0b47f52

纠错
反馈