about summary refs log tree commit diff stats
path: root/js
diff options
context:
space:
mode:
authorelioat <elioat@tilde.institute>2024-08-22 21:29:39 -0400
committerelioat <elioat@tilde.institute>2024-08-22 21:29:39 -0400
commit219801d28401d7283bf2e133cc16f0dc80999b49 (patch)
tree247d5884332aaa72a4dead877a14643bc6edfd24 /js
parent8ff754e4de53a227b0d02ac0e9b00e40d5cd49cc (diff)
downloadtour-219801d28401d7283bf2e133cc16f0dc80999b49.tar.gz
*
Diffstat (limited to 'js')
-rw-r--r--js/pixel-art/pixel/app.js186
-rw-r--r--js/pixel-art/pixel/index.html86
2 files changed, 272 insertions, 0 deletions
diff --git a/js/pixel-art/pixel/app.js b/js/pixel-art/pixel/app.js
new file mode 100644
index 0000000..087801c
--- /dev/null
+++ b/js/pixel-art/pixel/app.js
@@ -0,0 +1,186 @@
+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();
+    }
+}
\ No newline at end of file
diff --git a/js/pixel-art/pixel/index.html b/js/pixel-art/pixel/index.html
new file mode 100644
index 0000000..91f1813
--- /dev/null
+++ b/js/pixel-art/pixel/index.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Pixel Pixel Pixel Pixel Pixel Pixel</title>
+    <meta name="description" content="Draw me a goblin, please.">
+    <style>
+        body, html {
+            margin: 0;
+            padding: 0;
+            overflow: hidden;
+            background-color: teal;
+        }
+        button {
+            padding: 4px 10px;
+            font-size: 16px;
+            cursor: pointer;
+        }
+        #canvas {
+            display: block;
+        }
+        #palette {
+            position: absolute;
+            top: 10px;
+            right: 10px;
+            background-color: beige;
+            padding: 10px;
+            border: 1px solid #ccc;
+            border-radius: 5px;
+            width: 150px;
+        }
+
+        #palette label,
+        #palette input,
+        #palette button {
+            display: block;
+            margin-bottom: 10px;
+            width: 100%;
+        }
+
+        .color-history {
+            display: flex;
+            flex-wrap: wrap;
+        }
+
+        .color-history div {
+            width: 20px;
+            height: 20px;
+            border: 1px solid #000;
+            cursor: pointer;
+            margin-right: 5px;
+            margin-bottom: 5px;
+        }
+
+        .color-history {
+            display: flex;
+            margin-top: 10px;
+        }
+        .color-history div {
+            width: 20px;
+            height: 20px;
+            border: 1px solid #000;
+            cursor: pointer;
+            margin-right: 5px;
+        }
+    </style>
+</head>
+<body>
+    <canvas id="canvas"></canvas>
+    <div id="palette">
+        <label for="gridWidth">Grid Width:</label>
+        <input type="number" id="gridWidth" value="16" min="1">
+        <label for="gridHeight">Grid Height:</label>
+        <input type="number" id="gridHeight" value="16" min="1">
+        <br>
+        <label for="colorPicker">Select Color:</label>
+        <input type="color" id="colorPicker" value="#000000">
+        <div id="colorHistory" class="color-history"></div>
+        <button id="exportBtn">Export as PNG</button>
+        <button id="resetBtn">Reset</button>
+        <!--<input type="file" id="importBtn" accept="image/png">-->
+    </div>
+    <script src="app.js"></script>
+</body>
+</html>