You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React项目的Excalidraw组件中实现实时协作功能?

实现Excalidraw组件的实时协作功能及显示协作按钮

要给你当前的Excalidraw组件加上实时协作功能和顶部协作按钮,需要从前端组件配置和后端协作服务两方面入手,以下是具体实现步骤:

1. 核心原理说明

@excalidraw/excalidraw包仅提供前端协作的UI和CRDT(无冲突复制数据类型)逻辑,完整的实时协作需要你搭建一个WebSocket服务器来处理客户端之间的操作同步——也就是把A用户的绘图操作广播给房间内的其他用户,同时同步协作成员状态。

2. 修改Excalidraw组件配置

更新你的excalidrawComponent.js,添加协作相关的props和WebSocket通信逻辑:

import { useState, useEffect, useRef } from "react";

export default function Excalidraw(props) {
  const [ExcalidrawComp, setExcalidrawComp] = useState(null);
  const [collaborators, setCollaborators] = useState([]);
  // 可改为用户输入或随机生成的房间ID,用于标识协作会话
  const [roomId, setRoomId] = useState("demo-collab-room");
  const wsConnection = useRef(null);

  // 懒加载Excalidraw组件
  useEffect(() => {
    import("@excalidraw/excalidraw").then((mod) => setExcalidrawComp(mod.Excalidraw));
  }, []);

  // 初始化WebSocket连接,处理协作数据同步
  useEffect(() => {
    if (!ExcalidrawComp) return;

    // 替换成你的WebSocket服务地址,带上房间ID
    wsConnection.current = new WebSocket(`ws://your-collab-server-url/${roomId}`);

    wsConnection.current.onmessage = (event) => {
      const message = JSON.parse(event.data);
      switch (message.type) {
        case "collab-operation":
          // 同步其他用户的绘图操作到本地画布
          ExcalidrawComp.updateScene(message.payload);
          break;
        case "collaborators-update":
          // 更新协作成员列表
          setCollaborators(message.payload);
          break;
      }
    };

    // 组件卸载时关闭连接
    return () => wsConnection.current?.close();
  }, [ExcalidrawComp, roomId]);

  // 本地操作触发时,发送到服务器广播给其他用户
  const handleCollabUpdate = (update) => {
    if (wsConnection.current?.readyState === WebSocket.OPEN) {
      wsConnection.current.send(JSON.stringify({
        type: "collab-operation",
        payload: update,
        roomId,
        user: props.currentUser || { name: "匿名用户", color: "#2196F3" }
      }));
    }
  };

  return (
    <div className="excalidraw-component">
      {ExcalidrawComp && (
        <ExcalidrawComp
          // 启用协作模式
          isCollaborating={true}
          // 传递协作成员信息,画布上会显示对应光标
          collaborators={collaborators}
          // 本地操作触发回调,用于同步到服务器
          onCollabUpdate={handleCollabUpdate}
          // 显示顶部协作按钮
          toolbarCustomizations={{
            showCollaborationButton: true,
            onCollaborationButtonClick: () => {
              // 可自定义点击逻辑,比如弹出房间ID邀请框
              alert(`当前协作房间ID:${roomId},分享给他人即可协作`);
            }
          }}
          // 设置当前用户信息,用于协作光标标识
          currentUser={{
            name: "你",
            color: "#FF5722"
          }}
        />
      )}
    </div>
  );
}

3. 搭建WebSocket协作服务器

服务器需要实现以下核心功能:

  • 支持房间创建/加入逻辑,根据roomId分组客户端
  • 接收客户端发送的绘图操作,广播给同房间的其他所有客户端
  • 维护房间内的协作成员列表,当用户加入/离开时同步给所有成员

用Node.js + ws库快速搭建的核心逻辑示例:

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

// 存储房间和对应的客户端连接
const rooms = new Map();

wss.on('connection', (ws, req) => {
  // 从URL获取房间ID
  const roomId = req.url.slice(1);
  if (!rooms.has(roomId)) {
    rooms.set(roomId, new Set());
  }
  const room = rooms.get(roomId);
  room.add(ws);

  // 发送当前房间成员列表(简化示例)
  const collaborators = Array.from(room).map((_, idx) => ({
    name: `用户${idx+1}`,
    color: ['#FF5722', '#2196F3', '#4CAF50'][idx%3]
  }));
  broadcast(room, JSON.stringify({ type: "collaborators-update", payload: collaborators }));

  // 接收客户端操作并广播
  ws.on('message', (data) => {
    broadcast(room, data.toString());
  });

  // 用户断开连接时更新成员列表
  ws.on('close', () => {
    room.delete(ws);
    if (room.size === 0) {
      rooms.delete(roomId);
    } else {
      const updatedCollaborators = Array.from(room).map((_, idx) => ({
        name: `用户${idx+1}`,
        color: ['#FF5722', '#2196F3', '#4CAF50'][idx%3]
      }));
      broadcast(room, JSON.stringify({ type: "collaborators-update", payload: updatedCollaborators }));
    }
  });
});

// 广播消息给房间内所有客户端
function broadcast(room, message) {
  room.forEach((client) => {
    if (client.readyState === WebSocket.OPEN) {
      client.send(message);
    }
  });
}

关键注意事项

  • 确保WebSocket服务器配置跨域支持,否则前端会出现连接失败
  • 如果不想自己搭建后端,可以用第三方实时数据库(如Firebase Realtime Database)替代WebSocket服务器,适配Excalidraw的CRDT同步逻辑
  • 可以扩展房间ID的生成逻辑,比如随机生成唯一ID,或者让用户自定义

内容的提问来源于stack exchange,提问作者Sumit Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 22:20:41