Skip to content

Commit 69b6324

Browse files
updated
1 parent 7dc7227 commit 69b6324

File tree

6 files changed

+195
-59
lines changed

6 files changed

+195
-59
lines changed

images/erasor.png

772 KB
Loading

images/erasor.webp

189 KB
Loading

images/pen.webp

106 KB
Loading

index.html

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<head>
44
<meta charset="UTF-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6-
<title>Responsive Whiteboard</title>
6+
<title>Enhanced Whiteboard</title>
77
<link
88
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
99
rel="stylesheet"
@@ -44,37 +44,72 @@
4444
</div>
4545
</nav>
4646

47-
<!-- Flexbox Container -->
48-
<div class="d-flex flex-column vh-100">
49-
<!-- Controls Section -->
50-
<div id="controls" class="d-flex justify-content-around align-items-center bg-light p-3">
51-
<div>
52-
<label for="color" class="form-label">Brush Color</label>
53-
<input type="color" id="color" class="form-control form-control-color" value="#000000" />
54-
</div>
55-
<div>
56-
<label for="size" class="form-label">Brush Size</label>
57-
<input
58-
type="number"
59-
id="size"
60-
class="form-control"
61-
min="2"
62-
max="50"
63-
value="10"
64-
step="1"
65-
/>
66-
</div>
67-
<button id="clear" class="btn btn-danger">Clear</button>
68-
<button id="save" class="btn btn-success">Save Image</button>
69-
<div>
70-
<label for="upload" class="form-label">Upload Image</label>
71-
<input type="file" id="upload" class="form-control" accept="image/*" />
72-
</div>
47+
<!-- Main Layout -->
48+
<div class="container-fluid vh-100 d-flex flex-row">
49+
<!-- Side Menu -->
50+
<div id="side-menu" class="bg-light p-3 h-100">
51+
<button id="select-tool" class="btn btn-light w-100 mb-3" title="Select">
52+
<i class="fas fa-mouse-pointer"></i>
53+
</button>
54+
<button id="pen-tool" class="btn btn-light w-100 mb-3" title="Pen">
55+
<i class="fas fa-pen"></i>
56+
</button>
57+
<button id="eraser-tool" class="btn btn-light w-100 mb-3" title="Eraser">
58+
<i class="fas fa-eraser"></i>
59+
</button>
60+
<button id="draw-line" class="btn btn-light w-100 mb-3" title="Draw Line">
61+
<i class="fas fa-minus"></i>
62+
</button>
63+
<button id="draw-rect" class="btn btn-light w-100 mb-3" title="Draw Rectangle">
64+
<i class="far fa-square"></i>
65+
</button>
66+
<button id="draw-circle" class="btn btn-light w-100 mb-3" title="Draw Circle">
67+
<i class="far fa-circle"></i>
68+
</button>
7369
</div>
7470

75-
<!-- Canvas Section -->
76-
<div class="flex-grow-1 d-flex justify-content-center align-items-center bg-white">
77-
<canvas id="whiteboard"></canvas>
71+
<!-- Content Area -->
72+
<div class="flex-grow-1 d-flex flex-column">
73+
<!-- Controls Section -->
74+
<div id="controls" class="d-flex justify-content-around align-items-center bg-light p-3">
75+
<div>
76+
<label for="color" class="form-label">Brush Color</label>
77+
<input
78+
type="color"
79+
id="color"
80+
class="form-control form-control-color"
81+
value="#000000"
82+
/>
83+
</div>
84+
<div>
85+
<label for="size" class="form-label">Brush Size</label>
86+
<input
87+
type="number"
88+
id="size"
89+
class="form-control"
90+
min="2"
91+
max="50"
92+
value="10"
93+
step="1"
94+
/>
95+
</div>
96+
<button id="clear" class="btn btn-danger">Clear</button>
97+
<button id="save" class="btn btn-success">Save Image</button>
98+
<div>
99+
<label for="upload" class="form-label">Upload Image</label>
100+
<input
101+
type="file"
102+
id="upload"
103+
class="form-control"
104+
accept="image/*"
105+
/>
106+
</div>
107+
</div>
108+
109+
<!-- Canvas Section -->
110+
<div class="flex-grow-1 d-flex justify-content-center align-items-center bg-white">
111+
<canvas id="whiteboard"></canvas>
112+
</div>
78113
</div>
79114
</div>
80115

script.js

Lines changed: 95 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,26 @@
22
const canvas = document.getElementById("whiteboard");
33
const ctx = canvas.getContext("2d");
44

5-
// Set canvas to fill available space dynamically
5+
// Canvas setup
66
function resizeCanvas() {
7-
canvas.width = canvas.parentElement.offsetWidth;
8-
canvas.height = canvas.parentElement.offsetHeight;
9-
}
10-
resizeCanvas();
7+
// Save the current canvas content
8+
const savedContent = ctx.getImageData(0, 0, canvas.width, canvas.height);
9+
10+
// Resize the canvas
11+
canvas.width = canvas.parentElement.offsetWidth;
12+
canvas.height = canvas.parentElement.offsetHeight;
13+
14+
// Restore the saved content
15+
ctx.putImageData(savedContent, 0, 0);
16+
}
17+
resizeCanvas();
1118
window.addEventListener("resize", resizeCanvas);
1219

1320
// Variables for drawing
1421
let isDrawing = false;
1522
let brushColor = "#000000";
1623
let brushSize = 10;
17-
18-
// Event listeners for drawing
19-
canvas.addEventListener("mousedown", startDrawing);
20-
canvas.addEventListener("mousemove", draw);
21-
canvas.addEventListener("mouseup", stopDrawing);
22-
canvas.addEventListener("mouseout", stopDrawing);
24+
let currentTool = "pen"; // Tracks the active tool (pen, eraser, shapes)
2325

2426
// Event listeners for controls
2527
document.getElementById("color").addEventListener("input", (e) => {
@@ -43,43 +45,107 @@ document.getElementById("fullscreen").addEventListener("click", () => {
4345
document.documentElement.requestFullscreen();
4446
});
4547

48+
// Side menu tools
49+
document.getElementById("pen-tool").addEventListener("click", () => {
50+
currentTool = "pen";
51+
canvas.className = "pen";
52+
});
53+
54+
document.getElementById("eraser-tool").addEventListener("click", () => {
55+
currentTool = "eraser";
56+
canvas.className = "eraser";
57+
});
58+
59+
document.getElementById("select-tool").addEventListener("click", () => {
60+
currentTool = "select";
61+
canvas.className = "select";
62+
});
63+
64+
document.getElementById("draw-line").addEventListener("click", () => {
65+
currentTool = "line";
66+
});
67+
68+
document.getElementById("draw-rect").addEventListener("click", () => {
69+
currentTool = "rectangle";
70+
});
71+
72+
document.getElementById("draw-circle").addEventListener("click", () => {
73+
currentTool = "circle";
74+
});
75+
4676
// Drawing functions
47-
function startDrawing(e) {
77+
let startX, startY;
78+
79+
canvas.addEventListener("mousedown", (e) => {
4880
isDrawing = true;
49-
ctx.beginPath();
50-
ctx.moveTo(e.offsetX, e.offsetY);
51-
}
81+
startX = e.offsetX;
82+
startY = e.offsetY;
5283

53-
function draw(e) {
54-
if (!isDrawing) return;
84+
if (currentTool === "pen" || currentTool === "eraser") {
85+
ctx.beginPath();
86+
ctx.moveTo(startX, startY);
87+
}
88+
});
5589

56-
ctx.lineWidth = brushSize;
57-
ctx.lineCap = "round";
58-
ctx.strokeStyle = brushColor;
90+
canvas.addEventListener("mousemove", (e) => {
91+
if (!isDrawing) return;
5992

60-
ctx.lineTo(e.offsetX, e.offsetY);
61-
ctx.stroke();
62-
}
93+
if (currentTool === "pen") {
94+
ctx.lineWidth = brushSize;
95+
ctx.lineCap = "round";
96+
ctx.strokeStyle = brushColor;
97+
ctx.lineTo(e.offsetX, e.offsetY);
98+
ctx.stroke();
99+
} else if (currentTool === "eraser") {
100+
ctx.lineWidth = brushSize;
101+
ctx.lineCap = "round";
102+
ctx.strokeStyle = "#ffffff"; // Eraser color
103+
ctx.lineTo(e.offsetX, e.offsetY);
104+
ctx.stroke();
105+
}
106+
});
63107

64-
function stopDrawing() {
108+
canvas.addEventListener("mouseup", (e) => {
109+
if (!isDrawing) return;
65110
isDrawing = false;
66-
ctx.closePath();
67-
}
68111

69-
// Clear the canvas
112+
if (currentTool === "line") {
113+
ctx.lineWidth = brushSize;
114+
ctx.strokeStyle = brushColor;
115+
ctx.beginPath();
116+
ctx.moveTo(startX, startY);
117+
ctx.lineTo(e.offsetX, e.offsetY);
118+
ctx.stroke();
119+
} else if (currentTool === "rectangle") {
120+
const rectWidth = e.offsetX - startX;
121+
const rectHeight = e.offsetY - startY;
122+
ctx.lineWidth = brushSize;
123+
ctx.strokeStyle = brushColor;
124+
ctx.strokeRect(startX, startY, rectWidth, rectHeight);
125+
} else if (currentTool === "circle") {
126+
const radius = Math.sqrt(
127+
Math.pow(e.offsetX - startX, 2) + Math.pow(e.offsetY - startY, 2)
128+
);
129+
ctx.lineWidth = brushSize;
130+
ctx.strokeStyle = brushColor;
131+
ctx.beginPath();
132+
ctx.arc(startX, startY, radius, 0, Math.PI * 2);
133+
ctx.stroke();
134+
}
135+
});
136+
137+
// Utility functions
70138
function clearCanvas() {
71139
ctx.clearRect(0, 0, canvas.width, canvas.height);
72140
}
73141

74-
// Save the canvas as an image
75142
function saveImage() {
76143
const link = document.createElement("a");
77144
link.download = "whiteboard.png";
78145
link.href = canvas.toDataURL("image/png");
79146
link.click();
80147
}
81148

82-
// Upload an image to the canvas
83149
function uploadImage(e) {
84150
const file = e.target.files[0];
85151
if (!file) return;

style.css

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,38 @@ body {
1515
width: 100%;
1616
height: 100%;
1717
}
18+
19+
#side-menu {
20+
width: 80px;
21+
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
22+
}
23+
24+
canvas {
25+
border: 1px solid #ddd;
26+
width: 100%;
27+
height: 100%;
28+
}
29+
#side-menu {
30+
width: 80px;
31+
box-shadow: 2px 0 5px rgba(0, 0, 0, 0.1);
32+
}
33+
34+
canvas {
35+
border: 1px solid #ddd;
36+
width: 100%;
37+
height: 100%;
38+
cursor: crosshair; /* Default for drawing */
39+
}
40+
41+
canvas.eraser {
42+
cursor: url('./images/erasor.png') 16 16, auto; /* Custom eraser icon */
43+
}
44+
45+
canvas.pen {
46+
cursor: url(./images/pen.webp), auto; /* Custom pen icon */
47+
}
48+
49+
canvas.select {
50+
cursor: default; /* Default selection cursor */
51+
}
52+

0 commit comments

Comments
 (0)