<!DOCTYPE html>
<
html
lang
=
"en"
>
<
head
>
<
meta
charset
=
"UTF-8"
>
<
meta
name
=
"viewport"
content
=
"width=device-width, initial-scale=1.0"
>
<
title
>The Virtual Whiteboard</
title
>
<
style
>
.draggable {
cursor: move;
}
</
style
>
</
head
>
<
body
class
=
"bg-green-100"
>
<
div
class
=
"flex justify-center items-center h-screen"
>
<
div
class="max-w-3xl w-full bg-white
shadow-lg rounded-lg p-8">
<
h1
class="text-3xl font-semibold
mb-8 text-center">
Virtual Whiteboard
</
h1
>
<
div
class="border border-green-300
rounded-lg mb-6 p-4 relative">
<
div
class
=
"flex justify-center items-center"
>
<
canvas
id
=
"whiteboard"
width
=
"700"
height
=
"500"
></
canvas
>
</
div
>
<
div
class
=
"absolute top-0 right-0 p-2"
>
<
button
id
=
"clearBtn"
class="px-4 py-2 bg-blue-500
text-white rounded-lg
hover:bg-blue-600">
Clear
</
button
>
<
button
id
=
"eraserBtn"
class="ml-2 px-4 py-2 bg-red-500
text-white rounded-lg
hover:bg-red-600">
Eraser
</
button
>
</
div
>
</
div
>
<
div
class
=
"flex justify-between items-center mb-4"
>
<
div
class
=
"relative flex items-center"
>
<
label
for
=
"toolSelect"
class
=
"mr-2"
>
Tool:
</
label
>
<
select
id
=
"toolSelect"
class="px-3 py-2 bg-gray-200
rounded-lg appearance-none">
<
option
value
=
"pen"
>Pen</
option
>
<
option
value
=
"line"
>Line</
option
>
<
option
value
=
"rectangle"
>Rectangle</
option
>
<
option
value
=
"circle"
>Circle</
option
>
<
option
value
=
"text"
>Text</
option
>
</
select
>
</
div
>
<
div
>
<
button
id
=
"saveBtn"
class="px-4 py-2 bg-green-500
text-white rounded-lg
hover:bg-green-600">
Save
</
button
>
<
input
type
=
"file"
id
=
"imageInput"
accept
=
"image/*"
class
=
"hidden"
>
<
button
id
=
"imageBtn"
class="px-4 py-2 bg-yellow-500
text-white rounded-lg
hover:bg-yellow-600">
Insert Image
</
button
>
</
div
>
</
div
>
<
div
id
=
"textInput"
class
=
"mb-4 hidden"
>
<
input
type
=
"text"
id
=
"textBox"
class="border border-gray-300 rounded
px-3 py-2 focus:outline-none">
<
button
id
=
"textBtn"
class="ml-2 px-4 py-2 bg-blue-500
text-white rounded-lg
hover:bg-blue-600">
Add Text
</
button
>
</
div
>
</
div
>
</
div
>
<
script
>
const canvas = document.getElementById('whiteboard');
const context = canvas.getContext('2d');
let isDrawing = false;
let lastX = 0;
let lastY = 0;
let tool = 'pen';
let shapes = [];
let drag = false;
let dragStartX, dragStartY;
function draw(e) {
if (!isDrawing) return;
const { offsetX, offsetY } = e;
context.lineWidth = 2;
context.strokeStyle = '#000';
context.fillStyle = '#000';
if (tool === 'pen') {
context.lineTo(offsetX, offsetY);
context.stroke();
lastX = offsetX;
lastY = offsetY;
} else if (tool === 'line') {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.moveTo(lastX, lastY);
context.lineTo(offsetX, offsetY);
context.stroke();
} else if (tool === 'rectangle') {
context.clearRect(0, 0, canvas.width, canvas.height);
context.beginPath();
context.rect(lastX, lastY, offsetX - lastX, offsetY - lastY);
context.stroke();
} else if (tool === 'circle') {
context.clearRect(0, 0, canvas.width, canvas.height);
const radius = Math.sqrt(Math.pow(offsetX - lastX, 2) +
Math.pow(offsetY - lastY, 2));
context.beginPath();
context.arc(lastX, lastY, radius, 0, Math.PI * 2);
context.stroke();
}
}
canvas.addEventListener('mousedown', (e) => {
isDrawing = true;
if (tool !== 'pen') {
lastX = e.offsetX;
lastY = e.offsetY;
}
if (tool === 'line' || tool === 'rectangle' || tool === 'circle') {
drag = true;
dragStartX = e.offsetX;
dragStartY = e.offsetY;
}
});
canvas.addEventListener('mousemove', (e) => {
if (tool === 'pen' && isDrawing) {
draw(e);
} else if (tool === 'line' || tool === 'rectangle'
|| tool === 'circle') {
if (!drag) return;
const { offsetX, offsetY } = e;
context.clearRect(0, 0, canvas.width, canvas.height);
shapes.forEach(shape => {
if (shape.type === 'line') {
context.beginPath();
context.moveTo(shape.startX, shape.startY);
context.lineTo(shape.endX, shape.endY);
context.stroke();
} else if (shape.type === 'rectangle') {
context.beginPath();
context.rect(shape.startX, shape.startY,
shape.endX - shape.startX,
shape.endY - shape.startY);
context.stroke();
} else if (shape.type === 'circle') {
context.beginPath();
context.arc(shape.startX, shape.startY,
shape.radius, 0, Math.PI * 2);
context.stroke();
}
});
if (tool === 'line') {
context.beginPath();
context.moveTo(lastX, lastY);
context.lineTo(offsetX, offsetY);
context.stroke();
} else if (tool === 'rectangle') {
context.beginPath();
context.rect(lastX, lastY,
offsetX - lastX, offsetY - lastY);
context.stroke();
} else if (tool === 'circle') {
const radius = Math.sqrt(Math.pow(offsetX - lastX, 2) +
Math.pow(offsetY - lastY, 2));
context.beginPath();
context.arc(lastX, lastY, radius, 0, Math.PI * 2);
context.stroke();
}
}
});
canvas.addEventListener('mouseup', (e) => {
isDrawing = false;
if (tool === 'line' || tool === 'rectangle'
|| tool === 'circle') {
shapes.push({
type: tool,
startX: dragStartX,
startY: dragStartY,
endX: e.offsetX,
endY: e.offsetY,
radius: Math.sqrt(Math
.pow(e.offsetX - dragStartX, 2) +
Math.pow(e.offsetY - dragStartY, 2))
});
}
drag = false;
});
document.getElementById('clearBtn')
.addEventListener('click', () => {
context.clearRect(0, 0, canvas.width, canvas.height);
shapes = [];
});
document.getElementById('eraserBtn')
.addEventListener('click', () => {
tool = 'eraser';
});
canvas.addEventListener('mousemove', (e) => {
if (tool === 'eraser' && isDrawing) {
const { offsetX, offsetY } = e;
context.clearRect(offsetX - 5, offsetY - 5, 10, 10);
}
});
document.getElementById('toolSelect')
.addEventListener('change', (e) => {
tool = e.target.value;
if (tool === 'text') {
document.getElementById('textInput')
.classList.remove('hidden');
document.getElementById('textBox').focus();
} else {
document.getElementById('textInput')
.classList.add('hidden');
}
});
document.getElementById('textBtn')
.addEventListener('click', () => {
const text = document.getElementById('textBox')
.value;
context.font = '16px Arial';
context.fillText(text, lastX, lastY);
document.getElementById('textInput')
.classList.add('hidden');
tool = 'pen';
});
document.getElementById('imageBtn')
.addEventListener('click', () => {
document.getElementById('imageInput').click();
});
document.getElementById('imageInput')
.addEventListener('change', (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = () => {
const img = new Image();
img.onload = () => {
context.drawImage(img, 0, 0);
};
img.src = reader.result;
};
reader.readAsDataURL(file);
});
document.getElementById('saveBtn')
.addEventListener('click', () => {
const image = canvas.toDataURL('image/png');
const link = document.createElement('a');
link.href = image;
link.download = 'whiteboard.png';
link.click();
});
</
script
>
</
body
>
</
html
>