fabric.js + webSocket实现共享画板

文章介绍了如何利用fabric.js库,特别是在结合fabric-with-erasing扩展的情况下,实现在前端创建一个多人协作的画板应用。通过socket.io进行通信,确保用户间绘制动作的同步。代码示例展示了从初始化canvas,设置笔刷,监听鼠标事件到处理socket消息的完整流程。
摘要由CSDN通过智能技术生成

效果图

fabric.js官网

当前只介绍一对一,其实多对多也没什么差别,只是要创建一个Object或者Map保存每个人的笔刷

安装fabric或者fabric-with-erasing库,fabric-with-erasing携带着橡皮擦功能,也可以到官网定制功能

npm i fabric 
或者
npm i fabric-with-erasing

前端

<canvas
    width="1360"
    height="650"
    ref="canvasRef">
</canvas>

<script setup>
import { onMounted, ref, watch } from "vue";
import { fabric } from "fabric-with-erasing";
const canvasRef = ref(null);
const brushColor = ref("#000"); // 笔刷颜色
const brushWidth = ref(5); // 笔刷宽度
const brushType = ref("pencil"); // 当前工具
let canvas = null;
let drawing = null;
let socket = null;
let remoteBrush = null;

onMounted(async () => {
    initCanvas();
    // 初始化socket
    socket = await initSocket();
    initSocketEvent();
});

// 发送给房间其他用户绘制
function emitPaint({ event, data }) {
    socket.emit("paint", {
        type: brushType.value,
        event,
        data,
        brush: {
            color: brushColor.value,
            width: brushWidth.value,
        },
    });
}

// 设置笔刷
function setBrush(brush) {
    canvas.freeDrawingBrush = brush;
    canvas.freeDrawingBrush.width = brushWidth.value;
    canvas.freeDrawingBrush.color = brushColor.value;
}

function initCanvas() {
    canvas = new fabric.Canvas(canvasRef.value, {
        selection: false, //是否采用选区
        skipTargetFind: true, //跳过目标查找
        enableRetinaScaling: false, //是否启动缩放
        isDrawingMode: true, // 开启绘画模式
    });

    setBrush(new fabric.PencilBrush(canvas));
    initCanvasEvent();
}

// 初始化canvas事件
function initCanvasEvent() {
    canvas.on("mouse:down", (data) => {
        emitPaint({
            event: "MouseDown",
            data,
        });
        drawing = true;
    });

    canvas.on("mouse:move", (data) => {
        if (drawing) {
            emitPaint({
                event: "MouseMove",
                data,
            });
        }
    });

    canvas.on("mouse:up", (data) => {
        if (drawing) {
            emitPaint({
                event: "MouseUp",
                data,
            });
            drawing = false;
        }
    });
}

// 初始化socket事件
function initSocketEvent() {
    socket.on("painted", (data) => {
        if (data.event === "MouseDown") {
            if (data.type === "pencil") {
                remoteBrush = new fabric.PencilBrush(canvas);
            } else {
                remoteBrush = new fabric.EraserBrush(canvas);
            }
            remoteBrush.color = data.brush.color;
            remoteBrush.width = data.brush.width;
        }

        if (data.event === "MouseUp") {
            remoteBrush["on" + data.event](data.data);
        } else {
            remoteBrush["on" + data.event](data.data.pointer, data.data);
        }
    });
}
</script>

后端

socket.on("paint", async (data) => {
  	socket.broadcast.emit("painted", data);
});
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Vue 中使用 xterm.js 和 WebSocket 实现终端,你需要将用户输入的命令发送给后端,然后将后端返回的结果输出到 xterm.js 终端中。以下是一个简单的示例: ```html <template> <div id="terminal"></div> </template> <script> import { Terminal } from 'xterm'; import { FitAddon } from 'xterm-addon-fit'; export default { data() { return { socket: null, // WebSocket 实例 term: null, // Terminal 实例 }; }, mounted() { // 创建 WebSocket 实例 this.socket = new WebSocket('ws://localhost:8080'); // 创建 Terminal 实例 this.term = new Terminal(); const fitAddon = new FitAddon(); this.term.loadAddon(fitAddon); this.term.open(document.getElementById('terminal')); // 处理 WebSocket 消息 this.socket.onmessage = (event) => { this.term.write(event.data); }; // 处理输入事件 this.term.onData(data => { this.socket.send(data); }); // 调整终端大小 this.term.onResize(size => { const cols = size.cols; const rows = size.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }); // 发送 resize 消息 const cols = this.term.cols; const rows = this.term.rows; this.socket.send(JSON.stringify({ type: 'resize', cols, rows })); }, beforeDestroy() { // 关闭 WebSocket 连接 this.socket.close(); } } </script> ``` 以上代码中,我们首先在 `mounted` 钩子函数中创建了一个 WebSocket 实例和一个 Terminal 实例。然后我们为 WebSocket 实例添加了一个 `onmessage` 事件监听器,该监听器会在接收到服务器返回的消息时触发,我们在该事件处理函数中将消息输出到终端中。 接着,我们为 Terminal 实例添加了一个 `onData` 事件监听器,该监听器会在用户输入时触发,我们在该事件处理函数中向服务器发送用户输入的命令。同时,我们还为 Terminal 实例添加了一个 `onResize` 事件监听器,该监听器会在终端大小调整时触发,我们在该事件处理函数中向服务器发送终端大小变化的消息。 最后,我们在 `beforeDestroy` 钩子函数中关闭了 WebSocket 连接。 需要注意的是,以上代码中的 WebSocket 连接是通过 `ws://localhost:8080` 连接本地服务器的,你需要根据实际情况修改 WebSocket 连接地址。另外,代码中的消息格式和处理逻辑也需要根据实际情况进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值