about summary refs log blame commit diff stats
path: root/js/pixel-art/pixel/app.js
blob: 087801c5f1b273776c20905cd9737b0ba64c1a9f (plain) (tree)

























































































































































































                                                                                                
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const defaultGridWidth = 16;
const defaultGridHeight = 16;
let gridWidth = defaultGridWidth;
let gridHeight = defaultGridHeight;
let cellSize = 16;
let colorHistory = [];
let currentColor = '#000000';
let grid = Array(gridWidth).fill().map(() => Array(gridHeight).fill(null));
let offsetX = 0;
let offsetY = 0;

// Event Listeners
canvas.addEventListener('click', handleCanvasClick);
document.getElementById('colorPicker').addEventListener('input', handleColorChange);
document.getElementById('gridWidth').addEventListener('change', updateGridSize);
document.getElementById('gridHeight').addEventListener('change', updateGridSize);
document.getElementById('resetBtn').addEventListener('click', handleReset);
document.getElementById('exportBtn').addEventListener('click', exportToPNG);
window.addEventListener('keydown', handlePan);

// Initialization
resizeCanvas();
loadFromLocalStorage();

// Functions
function initializeGrid() {
    grid = Array(gridWidth).fill().map(() => Array(gridHeight).fill(null));
}

function resizeCanvas() {
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    centerGrid();
    drawGrid();
}

function centerGrid() {
    offsetX = Math.max((canvas.width - (gridWidth * cellSize)) / 2, 0);
    offsetY = Math.max((canvas.height - (gridHeight * cellSize)) / 2, 0);
}

function drawGrid() {
    ctx.fillStyle = 'teal';
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    ctx.strokeStyle = '#888888';
    for (let x = 0; x < gridWidth; x++) {
        for (let y = 0; y < gridHeight; y++) {
            ctx.fillStyle = grid[x][y] || '#f7f7f7';
            ctx.fillRect(x * cellSize + offsetX, y * cellSize + offsetY, cellSize, cellSize);
            ctx.strokeRect(x * cellSize + offsetX, y * cellSize + offsetY, cellSize, cellSize);
        }
    }
}

function addToColorHistory(color) {
    if (colorHistory.includes(color)) return;
    if (colorHistory.length >= 10) colorHistory.shift();
    colorHistory.push(color);
    renderColorHistory();
}

function renderColorHistory() {
    const historyDiv = document.getElementById('colorHistory');
    historyDiv.innerHTML = '';
    colorHistory.forEach(color => {
        const colorDiv = document.createElement('div');
        colorDiv.style.backgroundColor = color;
        colorDiv.addEventListener('click', () => {
            currentColor = color;
            document.getElementById('colorPicker').value = color;
        });
        historyDiv.appendChild(colorDiv);
    });
}

function handleColorChange() {
    currentColor = document.getElementById('colorPicker').value;
    addToColorHistory(currentColor);
    saveToLocalStorage();
}

function handleReset() {
    gridWidth = defaultGridWidth;
    gridHeight = defaultGridHeight;
    initializeGrid();
    centerGrid();
    drawGrid();
    localStorage.removeItem('pixelArtConfig');
    colorHistory = [];
    renderColorHistory();
    document.getElementById('gridWidth').value = gridWidth;
    document.getElementById('gridHeight').value = gridHeight;
    alert("Grid reset, color history cleared, and local storage cleared.");
}

function handlePan(e) {
    const step = cellSize;
    if (e.key === 'ArrowUp') offsetY += step;
    if (e.key === 'ArrowDown') offsetY -= step;
    if (e.key === 'ArrowLeft') offsetX += step;
    if (e.key === 'ArrowRight') offsetX -= step;
    drawGrid();
}

function updateGridSize() {
    gridWidth = parseInt(document.getElementById('gridWidth').value);
    gridHeight = parseInt(document.getElementById('gridHeight').value);
    initializeGrid();
    centerGrid();
    drawGrid();
    saveToLocalStorage();
}

function saveToLocalStorage() {
    const gridData = {
        gridWidth: gridWidth,
        gridHeight: gridHeight,
        cellSize: cellSize,
        colorHistory: colorHistory,
        currentColor: currentColor,
        grid: grid,
    };
    localStorage.setItem('pixelArtConfig', JSON.stringify(gridData));
}

function loadFromLocalStorage() {
    const savedData = localStorage.getItem('pixelArtConfig');
    if (savedData) {
        const gridData = JSON.parse(savedData);
        gridWidth = gridData.gridWidth || 10;
        gridHeight = gridData.gridHeight || 10;
        cellSize = gridData.cellSize || 16;
        colorHistory = gridData.colorHistory || [];
        currentColor = gridData.currentColor || '#000000';
        grid = gridData.grid || Array(gridWidth).fill().map(() => Array(gridHeight).fill(null));
        document.getElementById('gridWidth').value = gridWidth;
        document.getElementById('gridHeight').value = gridHeight;
        document.getElementById('colorPicker').value = currentColor;
        centerGrid();
        drawGrid();
    } else {
        initializeGrid();
        centerGrid();
        drawGrid();
    }
}

function exportToPNG() {
    const tempCanvas = document.createElement('canvas');
    const tempCtx = tempCanvas.getContext('2d');
    tempCanvas.width = gridWidth * cellSize;
    tempCanvas.height = gridHeight * cellSize;

    for (let x = 0; x < gridWidth; x++) {
        for (let y = 0; y < gridHeight; y++) {
            tempCtx.fillStyle = grid[x][y] || 'transparent';
            tempCtx.fillRect(x * cellSize, y * cellSize, cellSize, cellSize);
        }
    }

    tempCanvas.toBlob(blob => {
        const link = document.createElement('a');
        link.href = URL.createObjectURL(blob);
        link.download = 'pixel-art.png';
        link.click();
    });
}

function handleCanvasClick(e) {
    const rect = canvas.getBoundingClientRect();
    const x = Math.floor((e.clientX - rect.left - offsetX) / cellSize);
    const y = Math.floor((e.clientY - rect.top - offsetY) / cellSize);
    
    if (x >= 0 && x < gridWidth && y >= 0 && y < gridHeight) {
        if (e.detail === 2) {  // Double-click resets the cell
            grid[x][y] = null;
        } else {  // Single-click paints the cell with the current color
            grid[x][y] = currentColor;
        }
        drawGrid();
        saveToLocalStorage();
    }
}