当前只介绍一对一,其实多对多也没什么差别,只是要创建一个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);
});