document.addEventListener('DOMContentLoaded', () => { const backgroundMusic = document.getElementById('background-music'); backgroundMusic.play(); }); const canvas = document.getElementById('drawing-canvas'); const ctx = canvas.getContext('2d'); let drawing = false; let penColor = '#000000'; let penSize = 3; let erasing = false; const scale = 500 / 150; // scale factor for drawing let lastX, lastY; let strokes = []; let redoStrokes = []; // Stack to store undone strokes canvas.addEventListener('mousedown', startDrawing); canvas.addEventListener('mousemove', draw); canvas.addEventListener('mouseup', stopDrawing); canvas.addEventListener('mouseout', stopDrawing); document.getElementById('color-wheel').addEventListener('input', (event) => { penColor = event.target.value; updateColorInputs(penColor); }); document.getElementById('hex-code').addEventListener('input', (event) => { penColor = event.target.value; updateColorInputs(penColor); updateColorWheel(penColor); }); document.getElementById('r-value').addEventListener('input', updatePenColorFromRGB); document.getElementById('g-value').addEventListener('input', updatePenColorFromRGB); document.getElementById('b-value').addEventListener('input', updatePenColorFromRGB); document.getElementById('pen-size').addEventListener('input', (event) => { penSize = parseInt(event.target.value); }); document.getElementById('reset-color').addEventListener('click', () => { penColor = '#000000'; updateColorInputs(penColor); updateColorWheel(penColor); }); document.getElementById('reset-pen').addEventListener('click', () => { penSize = 3; document.getElementById('pen-size').value = penSize; }); document.getElementById('draw-button').addEventListener('click', () => { erasing = false; penColor = document.getElementById('color-wheel').value; // Reset to current pen color ctx.globalCompositeOperation = 'source-over'; // Draw normally }); document.getElementById('eraser-button').addEventListener('click', () => { erasing = true; ctx.globalCompositeOperation = 'destination-out'; // Erase }); document.getElementById('clear-canvas').addEventListener('click', clearCanvas); // Clear canvas document.getElementById('redo-button').addEventListener('click', redoLastStroke); // Redo last stroke document.getElementById('pause-music-button').addEventListener('click', toggleMusic); // Pause/Resume music document.getElementById('send-button').addEventListener('click', sendDrawing); document.addEventListener('keydown', (event) => { if (event.ctrlKey && event.key === 'z') { undoLastStroke(); } }); function startDrawing(event) { drawing = true; [lastX, lastY] = getMousePos(event); saveCanvasState(); draw(event); // Start drawing immediately } function draw(event) { if (!drawing) return; const [x, y] = getMousePos(event); if (!erasing) { ctx.fillStyle = penColor; } drawLine(lastX, lastY, x, y); [lastX, lastY] = [x, y]; } function stopDrawing() { drawing = false; } function getMousePos(event) { const rect = canvas.getBoundingClientRect(); const x = Math.floor((event.clientX - rect.left) / scale); const y = Math.floor((event.clientY - rect.top) / scale); return [x, y]; } function drawLine(x0, y0, x1, y1) { const dx = Math.abs(x1 - x0); const dy = Math.abs(y1 - y0); const sx = (x0 < x1) ? 1 : -1; const sy = (y0 < y1) ? 1 : -1; let err = dx - dy; while (true) { ctx.fillRect(x0 * scale, y0 * scale, penSize * scale, penSize * scale); // variable pen size scaled to canvas if (x0 === x1 && y0 === y1) break; const e2 = err * 2; if (e2 > -dy) { err -= dy; x0 += sx; } if (e2 < dx) { err += dx; y0 += sy; } } } function updateColorInputs(color) { document.getElementById('hex-code').value = color; const rgb = hexToRgb(color); document.getElementById('r-value').value = rgb.r; document.getElementById('g-value').value = rgb.g; document.getElementById('b-value').value = rgb.b; } function updateColorWheel(color) { document.getElementById('color-wheel').value = color; } function updatePenColorFromRGB() { const r = parseInt(document.getElementById('r-value').value) || 0; const g = parseInt(document.getElementById('g-value').value) || 0; const b = parseInt(document.getElementById('b-value').value) || 0; penColor = rgbToHex(r, g, b); updateColorInputs(penColor); updateColorWheel(penColor); } function hexToRgb(hex) { const bigint = parseInt(hex.slice(1), 16); const r = (bigint >> 16) & 255; const g = (bigint >> 8) & 255; const b = bigint & 255; return { r, g, b }; } function rgbToHex(r, g, b) { return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase(); } function saveCanvasState() { const dataUrl = canvas.toDataURL(); strokes.push(dataUrl); redoStrokes = []; // Clear redo stack on new action } function undoLastStroke() { if (strokes.length > 0) { const lastStroke = strokes.pop(); redoStrokes.push(lastStroke); // Push undone stroke to redo stack if (strokes.length > 0) { const img = new Image(); img.src = strokes[strokes.length - 1]; img.onload = () => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0); }; } else { clearCanvas(); // Clear canvas if no strokes are left } } } function redoLastStroke() { if (redoStrokes.length > 0) { const lastRedoStroke = redoStrokes.pop(); strokes.push(lastRedoStroke); const img = new Image(); img.src = lastRedoStroke; img.onload = () => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(img, 0, 0); }; } } function clearCanvas() { ctx.clearRect(0, 0, canvas.width, canvas.height); strokes = []; redoStrokes = []; // Clear both stacks } function toggleMusic() { const backgroundMusic = document.getElementById('background-music'); if (backgroundMusic.paused) { backgroundMusic.play(); document.getElementById('pause-music-button').innerText = 'Pause Music'; } else { backgroundMusic.pause(); document.getElementById('pause-music-button').innerText = 'Resume Music'; } } function sendDrawing() { const title = document.getElementById('drawing-title').value; const username = document.getElementById('username').value; const note = document.getElementById('note').value; if (!title || !username || !note) { alert('Title, username, and note must not be blank.'); return; } const image = canvas.toDataURL('image/png'); const data = { title: title, username: username, note: note, image: image }; fetch('/upload', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(data) }) .then(response => response.json()) .then(data => { if (data.message) { alert(data.message); } else { alert('Failed to send drawing.'); } }) .catch(error => { console.error('Error:', error); alert('An error occurred while sending the drawing.'); }); }