fullscreen drawing

This commit is contained in:
JurajKubrican
2025-02-28 16:41:29 +01:00
committed by Juraj Kubrican
parent 0505964854
commit 7ed413648c
11 changed files with 345 additions and 142 deletions

138
js/draw.ts Normal file
View File

@@ -0,0 +1,138 @@
(() => {
const drawElement = document.getElementById(
"drawDiv"
) as HTMLDivElement | null;
if (!drawElement) {
throw new Error("canvas not found");
}
type DrawPoint = {
x: number;
y: number;
};
type DrawEvent = {
from: DrawPoint;
to: DrawPoint;
};
type Events = {
draw: DrawEvent;
};
const drawEmitter = mitt<Events>();
let drawing = false;
const socketUrl = "/draw/ws";
let socket = new WebSocket(socketUrl);
socket.onerror = console.error;
socket.onclose = console.warn;
const serializeDraw = ({from, to }: DrawEvent) =>
`${from.x},${from.y},${to.x},${to.y}`;
const deserializeDraw = (message: string): DrawEvent => {
const parts = message.split(",");
return {
from: {
x: Number(parts[0]),
y: Number(parts[1]),
},
to: {
x: Number(parts[2]),
y: Number(parts[3]),
},
};
};
drawEmitter.on("draw", (e) => sendMessage(e));
const sendMessage = (e: DrawEvent) => {
if (socket.readyState !== socket.OPEN) {
socket = new WebSocket(socketUrl);
}
socket.send(serializeDraw(e));
};
const mouseDown = () => {
drawing = true;
previous=null
};
const mouseUp = () => {
drawing = false;
};
let previous: DrawPoint | null = null;
const mouseMove = (e: Pick<MouseEvent, "offsetX" | "offsetY">) => {
if (!drawing) return;
if (previous) {
drawEmitter.emit("draw", {
from: previous,
to: { x: e.offsetX, y: e.offsetY },
});
}
previous = { x: e.offsetX, y: e.offsetY };
};
const touchMove = (e: TouchEvent) => {
e.preventDefault();
mouseMove({
offsetX: e.touches[0].clientX - drawElement.offsetLeft,
offsetY: e.touches[0].clientY - drawElement.offsetTop,
});
};
drawElement.addEventListener("mousedown", mouseDown);
drawElement.addEventListener("mouseup", mouseUp);
drawElement.addEventListener("mousemove", mouseMove);
drawElement.addEventListener("touchstart", mouseDown);
drawElement.addEventListener("touchend", mouseUp);
drawElement.addEventListener("touchmove", touchMove);
const receiveCanvas = document.getElementById(
"receiveCanvas"
) as HTMLCanvasElement | null;
const recCtx = receiveCanvas?.getContext("2d");
if (!recCtx || !receiveCanvas) {
throw new Error("canvas not found");
}
//@ts-expect-error
window.ctx = recCtx;
setTimeout(()=>{
recCtx.lineWidth = 2;
recCtx.lineCap = "round";
recCtx.strokeStyle = "white";
},10)
socket.addEventListener("message", (event) => {
if(event.data==="ping" || event.data.startsWith('pong')) return
const { from, to } = deserializeDraw(event.data);
recCtx.beginPath();
recCtx.moveTo(from.x, from.y);
recCtx.lineTo(to.x, to.y);
recCtx.closePath();
recCtx.stroke();
console.log(from, to);
});
setInterval(() => {
if (socket.readyState !== socket.OPEN) {
socket = new WebSocket(socketUrl);
}
socket.send("ping");
}, 10000);
const resizeObserver = new ResizeObserver((entries) => {
const entry = entries.at(0);
receiveCanvas.height = entry?.contentRect.height ?? 500;
receiveCanvas.width = entry?.contentRect.width ?? 500;
});
resizeObserver.observe(drawElement);
})();