Skip to content

Commit fd8425b

Browse files
committed
feat: Implemented the rectangle box feature in canvas.jsx
1 parent bb7ba67 commit fd8425b

File tree

1 file changed

+32
-41
lines changed

1 file changed

+32
-41
lines changed

client/src/components/Canvas.jsx

Lines changed: 32 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,39 +13,32 @@ export const Canvas = () => {
1313
const [isDrawing, setIsDrawing] = useState(false);
1414
const [isCanvasFocused, setIsCanvasFocused] = useState(false);
1515

16-
// For line tool
1716
const startPoint = useRef({ x: 0, y: 0 });
1817
const snapshot = useRef(null);
1918

2019
// Collaboration
2120
const [roomId, setRoomId] = useState("");
22-
const [joined, setJoined] = useState(false); // false = local mode
21+
const [joined, setJoined] = useState(false);
2322
const [socket, setSocket] = useState(null);
24-
const [isModalOpen, setIsModalOpen] = useState(false); // controls modal visibility
23+
const [isModalOpen, setIsModalOpen] = useState(false);
2524

26-
// Initialize socket connection (always available but idle until joined)
2725
useEffect(() => {
2826
const s = io("http://localhost:3000");
2927
setSocket(s);
30-
3128
s.on("connect", () => console.log("Connected to server:", s.id));
32-
3329
s.on("draw", ({ x, y, color, width, type, tool }) => {
34-
if (!joined) return; // only listen when in collab mode
30+
if (!joined) return;
3531
const ctx = canvasRef.current?.getContext("2d");
3632
if (!ctx) return;
37-
3833
if (type === "start") ctx.beginPath();
3934
ctx.strokeStyle = tool === "eraser" ? "#ffffff" : color;
4035
ctx.lineWidth = tool === "eraser" ? width * 3 : width;
4136
ctx.lineTo(x, y);
4237
ctx.stroke();
4338
});
44-
4539
return () => s.disconnect();
4640
}, [joined]);
4741

48-
// Canvas setup
4942
useEffect(() => {
5043
const canvas = canvasRef.current;
5144
if (!canvas) return;
@@ -54,20 +47,17 @@ export const Canvas = () => {
5447
canvas.height = window.innerHeight;
5548
ctx.lineCap = "round";
5649
ctx.lineJoin = "round";
57-
5850
const handleResize = () => {
5951
const image = ctx.getImageData(0, 0, canvas.width, canvas.height);
6052
canvas.width = window.innerWidth;
6153
canvas.height = window.innerHeight;
6254
ctx.putImageData(image, 0, 0);
6355
};
64-
6556
window.addEventListener("resize", handleResize);
6657
toast.success("Canvas ready! Local mode active.");
6758
return () => window.removeEventListener("resize", handleResize);
6859
}, []);
6960

70-
// Keyboard shortcuts
7161
useEffect(() => {
7262
const handleKeyDown = (e) => {
7363
if (!isCanvasFocused) return;
@@ -79,23 +69,19 @@ export const Canvas = () => {
7969
return () => window.removeEventListener("keydown", handleKeyDown);
8070
}, [isCanvasFocused]);
8171

82-
// Drawing logic
72+
// Drawing logic handlers
8373
const startDrawing = (e) => {
8474
const canvas = canvasRef.current;
8575
const ctx = canvas?.getContext("2d");
8676
if (!ctx) return;
87-
8877
const rect = canvas.getBoundingClientRect();
8978
const x = e.clientX - rect.left;
9079
const y = e.clientY - rect.top;
91-
9280
startPoint.current = { x, y };
9381
setIsDrawing(true);
94-
9582
if (activeTool === "pen" || activeTool === "eraser") {
9683
ctx.beginPath();
9784
ctx.moveTo(x, y);
98-
9985
if (joined && socket)
10086
socket.emit("draw", {
10187
roomId,
@@ -107,8 +93,8 @@ export const Canvas = () => {
10793
tool: activeTool,
10894
});
10995
}
110-
111-
if (activeTool === "line") {
96+
// Save snapshot for preview tools
97+
if (activeTool === "line" || activeTool === "rectangle") {
11298
snapshot.current = ctx.getImageData(0, 0, canvas.width, canvas.height);
11399
}
114100
};
@@ -118,17 +104,14 @@ export const Canvas = () => {
118104
const canvas = canvasRef.current;
119105
const ctx = canvas?.getContext("2d");
120106
if (!ctx) return;
121-
122107
const rect = canvas.getBoundingClientRect();
123108
const x = e.clientX - rect.left;
124109
const y = e.clientY - rect.top;
125-
126110
if (activeTool === "pen" || activeTool === "eraser") {
127111
ctx.strokeStyle = activeTool === "eraser" ? "#ffffff" : activeColor;
128112
ctx.lineWidth = activeTool === "eraser" ? strokeWidth * 3 : strokeWidth;
129113
ctx.lineTo(x, y);
130114
ctx.stroke();
131-
132115
if (joined && socket)
133116
socket.emit("draw", {
134117
roomId,
@@ -148,6 +131,17 @@ export const Canvas = () => {
148131
ctx.lineWidth = strokeWidth;
149132
ctx.stroke();
150133
ctx.closePath();
134+
} else if (activeTool === "rectangle") {
135+
ctx.putImageData(snapshot.current, 0, 0);
136+
ctx.beginPath();
137+
const startX = startPoint.current.x;
138+
const startY = startPoint.current.y;
139+
const width = x - startX;
140+
const height = y - startY;
141+
ctx.strokeStyle = activeColor;
142+
ctx.lineWidth = strokeWidth;
143+
ctx.strokeRect(startX, startY, width, height);
144+
ctx.closePath();
151145
}
152146
};
153147

@@ -192,27 +186,26 @@ export const Canvas = () => {
192186
onToolChange={handleToolChange}
193187
onClear={handleClear}
194188
/>
195-
196-
{joined ? <button
197-
onClick={() => handleExitRoom()}
198-
className="fixed top-4 right-4 bg-red-700 text-white px-4 py-2 rounded-lg shadow hover:bg-red-800 z-50"
199-
>
200-
Exit Room
201-
</button>
202-
: <button
203-
onClick={() => setIsModalOpen(true)}
204-
className="fixed top-4 right-4 bg-blue-600 text-white px-4 py-2 rounded-lg shadow hover:bg-blue-700 z-50"
205-
>
206-
Collaborate
207-
</button> }
208-
209-
189+
{joined ? (
190+
<button
191+
onClick={() => handleExitRoom()}
192+
className="fixed top-4 right-4 bg-red-700 text-white px-4 py-2 rounded-lg shadow hover:bg-red-800 z-50"
193+
>
194+
Exit Room
195+
</button>
196+
) : (
197+
<button
198+
onClick={() => setIsModalOpen(true)}
199+
className="fixed top-4 right-4 bg-blue-600 text-white px-4 py-2 rounded-lg shadow hover:bg-blue-700 z-50"
200+
>
201+
Collaborate
202+
</button>
203+
)}
210204
<ColorPicker activeColor={activeColor} onColorChange={setActiveColor} />
211205
<StrokeControl
212206
strokeWidth={strokeWidth}
213207
onStrokeWidthChange={setStrokeWidth}
214208
/>
215-
216209
<canvas
217210
ref={canvasRef}
218211
tabIndex={0}
@@ -224,7 +217,6 @@ export const Canvas = () => {
224217
onMouseLeave={stopDrawing}
225218
className="cursor-crosshair focus:outline-2 focus:outline-primary"
226219
/>
227-
228220
{isModalOpen && (
229221
<div className="fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-white/90 border border-gray-400 rounded-xl shadow-xl p-6 z-50 flex flex-col items-center gap-3">
230222
<h2 className="text-xl font-semibold">Join a Room</h2>
@@ -249,7 +241,6 @@ export const Canvas = () => {
249241
</button>
250242
</div>
251243
)}
252-
253244
<div className="fixed bottom-6 left-1/2 -translate-x-1/2 pointer-events-none">
254245
<div className="bg-toolbar/95 border border-toolbar-border rounded-xl shadow-lg backdrop-blur-sm px-6 py-3">
255246
<p className="text-sm text-foreground font-medium">

0 commit comments

Comments
 (0)