This Chat is read-only. Login to resume chatting.
git add .
git commit -m "Initial commit"
git push origin main<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Paint App</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎨</text></svg>">
<style>
body, html {
margin: 0;
padding: 0;
overflow: hidden;
height: 100%;
background-color: #f0f0f0;
font-family: Arial, sans-serif;
}
#canvasContainer {
position: relative;
width: 100vw;
height: 100vh;
}
#controls {
position: absolute;
top: 20px;
left: 20px;
background-color: rgba(255, 255, 255, 0.8);
color: #333;
padding: 20px;
box-shadow: 2px 2px 10px rgba(0, 0, 0, 0.3);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 15px;
border-radius: 10px;
max-width: calc(100% - 40px); /* Ensure it doesn't overflow the viewport */
}
#controls button {
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
background-color: #555;
color: #fff;
cursor: pointer;
transition: background-color 0.3s;
font-size: 1.2em;
}
#controls button:hover {
background-color: #777;
}
.popover {
position: absolute;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
padding: 10px;
display: none;
z-index: 10;
}
#paintCanvas {
width: 100%;
height: 100%;
background-color: #fff;
}
</style>
</head>
<body>
<div id="canvasContainer">
<div id="controls">
<button id="colorPickerButton">🖌</button>
<div class="popover" id="colorPickerPopover">
<input type="color" id="colorPicker" value="#000000">
</div>
<button id="backgroundColorPickerButton">🎨</button>
<div class="popover" id="backgroundColorPickerPopover">
<input type="color" id="backgroundColorPicker" value="#ffffff">
</div>
<button id="brushSizeButton">🖌️</button>
<div class="popover" id="brushSizePopover">
<input type="range" id="brushSize" min="1" max="50" value="5">
</div>
<button id="clearButton">🗑️</button>
<button id="exportButton">📤</button>
<button id="toggleGridButton">🏁</button>
<button id="undoButton">⟲</button>
<button id="redoButton">⟳</button>
</div>
<canvas id="paintCanvas"></canvas>
<canvas id="offscreenCanvas" style="display: none;"></canvas>
</div>
<script>
const canvas = document.getElementById('paintCanvas');
const offscreenCanvas = document.getElementById('offscreenCanvas');
const offscreenCtx = offscreenCanvas.getContext('2d');
const ctx = canvas.getContext('2d');
const colorPicker = document.getElementById('colorPicker');
const backgroundColorPicker = document.getElementById('backgroundColorPicker');
const brushSize = document.getElementById('brushSize');
const clearButton = document.getElementById('clearButton');
const exportButton = document.getElementById('exportButton');
const toggleGridButton = document.getElementById('toggleGridButton');
const undoButton = document.getElementById('undoButton');
const redoButton = document.getElementById('redoButton');
const colorPickerButton = document.getElementById('colorPickerButton');
const backgroundColorPickerButton = document.getElementById('backgroundColorPickerButton');
const brushSizeButton = document.getElementById('brushSizeButton');
const colorPickerPopover = document.getElementById('colorPickerPopover');
const backgroundColorPickerPopover = document.getElementById('backgroundColorPickerPopover');
const brushSizePopover = document.getElementById('brushSizePopover');
let painting = false;
let lastX = 0;
let lastY = 0;
let showGrid = false;
let commands = [];
let currentCommandIndex = -1;
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
offscreenCanvas.width = window.innerWidth;
offscreenCanvas.height = window.innerHeight;
setBackgroundColor();
if (showGrid) drawGrid();
}
function getMousePos(canvas, evt) {
const rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
function startPosition(e) {
painting = true;
const mousePos = getMousePos(canvas, e);
lastX = mousePos.x;
lastY = mousePos.y;
ctx.beginPath();
ctx.moveTo(lastX, lastY);
offscreenCtx.beginPath();
offscreenCtx.moveTo(lastX, lastY);
}
function endPosition() {
painting = false;
ctx.beginPath();
offscreenCtx.beginPath();
saveCommand();
}
function draw(e) {
if (!painting) return;
ctx.lineWidth = brushSize.value;
ctx.lineCap = 'round';
ctx.strokeStyle = colorPicker.value;
offscreenCtx.lineWidth = brushSize.value;
offscreenCtx.lineCap = 'round';
offscreenCtx.strokeStyle = colorPicker.value;
const mousePos = getMousePos(canvas, e);
ctx.lineTo(mousePos.x, mousePos.y);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(mousePos.x, mousePos.y);
offscreenCtx.lineTo(mousePos.x, mousePos.y);
offscreenCtx.stroke();
offscreenCtx.beginPath();
offscreenCtx.moveTo(mousePos.x, mousePos.y);
lastX = mousePos.x;
lastY = mousePos.y;
}
function clearCanvas() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
offscreenCtx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
setBackgroundColor();
if (showGrid) drawGrid();
saveCommand();
}
function exportCanvas() {
const link = document.createElement('a');
link.download = 'painting.png';
link.href = canvas.toDataURL();
link.click();
}
function setBackgroundColor() {
const backgroundColor = backgroundColorPicker.value;
ctx.fillStyle = backgroundColor;
ctx.fillRect(0, 0, canvas.width, canvas.height);
offscreenCtx.fillStyle = backgroundColor;
offscreenCtx.fillRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
}
function drawGrid() {
const gridSize = 20;
ctx.strokeStyle = 'rgba(0, 0, 0, 0.1)';
ctx.lineWidth = 1;
for (let x = 0; x <= canvas.width; x += gridSize) {
ctx.beginPath();
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
for (let y = 0; y <= canvas.height; y += gridSize) {
ctx.beginPath();
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
}
function toggleGrid() {
showGrid = !showGrid;
if (showGrid) {
drawGrid();
} else {
// Redraw the canvas without the grid
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(offscreenCanvas, 0, 0);
}
}
function showPopover(button, popover) {
const rect = button.getBoundingClientRect();
popover.style.display = 'block';
popover.style.left = `${rect.right + 10}px`;
popover.style.top = `${rect.top}px`;
}
function hidePopover(popover) {
popover.style.display = 'none';
}
function handleClickOutside(event) {
if (!colorPickerPopover.contains(event.target) && !colorPickerButton.contains(event.target)) {
hidePopover(colorPickerPopover);
}
if (!backgroundColorPickerPopover.contains(event.target) && !backgroundColorPickerButton.contains(event.target)) {
hidePopover(backgroundColorPickerPopover);
}
if (!brushSizePopover.contains(event.target) && !brushSizeButton.contains(event.target)) {
hidePopover(brushSizePopover);
}
}
function saveCommand() {
// Save the current state of the canvas
commands = commands.slice(0, currentCommandIndex + 1);
commands.push(offscreenCanvas.toDataURL());
currentCommandIndex++;
}
function undo() {
if (currentCommandIndex > 0) {
currentCommandIndex--;
const imageData = commands[currentCommandIndex];
const img = new Image();
img.src = imageData;
img.onload = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
offscreenCtx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
offscreenCtx.drawImage(img, 0, 0);
};
}
}
function redo() {
if (currentCommandIndex < commands.length - 1) {
currentCommandIndex++;
const imageData = commands[currentCommandIndex];
const img = new Image();
img.src = imageData;
img.onload = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(img, 0, 0);
offscreenCtx.clearRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
offscreenCtx.drawImage(img, 0, 0);
};
}
}
function initializeCanvas() {
setBackgroundColor();
saveCommand(); // Save the initial state
}
colorPickerButton.addEventListener('click', () => showPopover(colorPickerButton, colorPickerPopover));
backgroundColorPickerButton.addEventListener('click', () => showPopover(backgroundColorPickerButton, backgroundColorPickerPopover));
brushSizeButton.addEventListener('click', () => showPopover(brushSizeButton, brushSizePopover));
colorPicker.addEventListener('change', () => hidePopover(colorPickerPopover));
backgroundColorPicker.addEventListener('change', () => {
hidePopover(backgroundColorPickerPopover);
setBackgroundColor();
});
brushSize.addEventListener('change', () => hidePopover(brushSizePopover));
backgroundColorPicker.addEventListener('input', setBackgroundColor);
canvas.addEventListener('mousedown', startPosition);
canvas.addEventListener('mouseup', endPosition);
canvas.addEventListener('mousemove', draw);
clearButton.addEventListener('click', clearCanvas);
exportButton.addEventListener('click', exportCanvas);
toggleGridButton.addEventListener('click', toggleGrid);
undoButton.addEventListener('click', undo);
redoButton.addEventListener('click', redo);
document.addEventListener('click', handleClickOutside);
// Initialize the background color and resize the canvas
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
initializeCanvas();
</script>
</body>
</html>