Sure! To create a GitHub repository for this page and deploy it on Vercel, follow these steps:
Step 1: Create a GitHub Repository
-
Create a new repository on GitHub:
- Go to GitHub and log in.
- Click on the "+" icon in the top right corner and select "New repository."
- Name your repository (e.g.,
paint-app-professional).
- Choose to make it public or private.
- Click "Create repository."
-
Clone the repository to your local machine:
git clone https://github.com/your-username/paint-app-professional.git
cd paint-app-professional
-
Create the necessary files:
- Create an
index.html file and paste the HTML content from the canvas into this file.
- Create a
README.md file to describe your project.
-
Add the files to the repository:
git add .
git commit -m "Initial commit"
git push origin main
Step 2: Deploy on Vercel
-
Install Vercel CLI:
-
Login to Vercel:
- Run the following command to log in to Vercel:
-
Deploy your project:
-
Link your GitHub repository to Vercel:
- Vercel will prompt you to link your GitHub repository. Follow the instructions to link your repository.
- Once linked, Vercel will automatically deploy your project whenever you push changes to the
main branch.
Example Directory Structure
Your project directory should look something like this:
paint-app-professional/
├── index.html
├── README.md
Example index.html
Here is the index.html file with the canvas content:
<!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>
Step 3: Deploy on Vercel
-
Install Vercel CLI:
-
Login to Vercel:
- Run the following command to log in to Vercel:
-
Deploy your project:
-
Link your GitHub repository to Vercel:
- Vercel will prompt you to link your GitHub repository. Follow the instructions to link your repository.
- Once linked, Vercel will automatically deploy your project whenever you push changes to the
main branch.
That's it! Your project should now be deployed on Vercel, and any changes pushed to the main branch of your GitHub repository will automatically trigger a new deployment.