Pixel Art Maker For Melon Playground -

// get mouse / touch coordinates to grid cell function getGridCoordFromEvent(e) const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; // canvas physical vs CSS const scaleY = canvas.height / rect.height; let clientX, clientY; if(e.touches) // touch event clientX = e.touches[0].clientX; clientY = e.touches[0].clientY; else clientX = e.clientX; clientY = e.clientY; let canvasX = (clientX - rect.left) * scaleX; let canvasY = (clientY - rect.top) * scaleY; canvasX = Math.min(Math.max(0, canvasX), canvas.width - 0.01); canvasY = Math.min(Math.max(0, canvasY), canvas.height - 0.01); const col = Math.floor(canvasX / cellW); const row = Math.floor(canvasY / cellH); return row, col ;

body background: linear-gradient(145deg, #1a2a3a 0%, #0f1a24 100%); display: flex; justify-content: center; align-items: center; min-height: 100vh; font-family: 'Segoe UI', 'Courier New', 'Fira Code', monospace; margin: 0; padding: 20px;

// ---- fill with current selected color (not only bg) but fill tool ---- function floodFillTool(targetRow, targetCol, newColor) // typical flood fill 4-direction if(pixelMatrix[targetRow][targetCol] === newColor) return; const targetColor = pixelMatrix[targetRow][targetCol]; const stack = [row: targetRow, col: targetCol]; const visited = Array(currentGridSize).fill().map(() => Array(currentGridSize).fill(false)); while(stack.length)

// ---------- state ---------- let currentGridSize = 32; // 32x32 default let cellW = 0, cellH = 0; let pixelMatrix = []; // 2D array storing hex colors let isDrawing = false; let eraseMode = false; // erase with background color (default dark bg) pixel art maker for melon playground

// update single cell in matrix & canvas function setPixel(row, col, color)

/* tool panel */ .tools-panel display: flex; flex-wrap: wrap; justify-content: center; gap: 1rem; margin-bottom: 1.5rem; align-items: center; background: #202433cc; padding: 0.8rem 1.2rem; border-radius: 60px; backdrop-filter: blur(4px);

// clear to default bg function clearCanvas() fillAllWithColor(DEFAULT_BG); // get mouse / touch coordinates to grid

function handlePointerMove(e) if(!isDrawing) return; e.preventDefault(); // for mouse move, if right button held down, we treat as erase let forceErase = eraseMode; if(e.buttons === 2) // right button forceErase = true; else if(e.buttons === 1 && !eraseMode) forceErase = false; else if(e.buttons === 1 && eraseMode) forceErase = true; else forceErase = eraseMode; paintAtEvent(e, forceErase);

function handlePointerEnd(e) isDrawing = false; // reset erase mode to default (based on next click, no persistent) eraseMode = false;

footer font-size: 0.7rem; text-align: center; color: #8aaec0; margin-top: 12px; const scaleX = canvas.width / rect.width

<!-- canvas grid container --> <div class="canvas-area"> <canvas id="pixelCanvas" width="320" height="320" style="image-rendering: crisp-edges; image-rendering: pixelated; image-rendering: pixelated; width: 320px; height: 320px;"></canvas> </div>

.melon-badge background: #00000055; border-radius: 28px; text-align: center; font-size: 0.7rem; padding: 6px 10px; color: #ffe1aa; margin-top: 12px; font-weight: bold;

.size-control display: flex; align-items: center; gap: 12px; background: #171c26; padding: 5px 15px; border-radius: 40px; .size-control span color: #ffcf8a; font-weight: bold;

#currentColorPicker width: 48px; height: 48px; border: 3px solid white; border-radius: 50%; cursor: pointer; background: #ff44aa; box-shadow: 0 2px 8px black; transition: transform 0.1s ease; #currentColorPicker:active transform: scale(0.95);