Created
May 2, 2024 22:13
-
-
Save EncodeTheCode/25f3fb71740a79cdbda08730837435a1 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<title>Colorable Grid</title> | |
<style> | |
#grid-container { | |
margin: 0 0; | |
padding: 0 0; | |
display: grid; | |
grid-template-columns: repeat(80, 5px); | |
grid-template-rows: repeat(8, 5px); | |
gap: 0; /* No gap between grid squares */ | |
border: 0px solid #000000; /* 1px solid black border around the entire grid */ | |
} | |
.grid-square { | |
width: 10px; | |
height: 10px; | |
border: 1px solid #000000; /* 1px solid black border for each grid square */ | |
cursor: pointer; | |
} | |
#color-picker-container { | |
display: flex; | |
align-items: center; | |
margin-top: 20px; | |
} | |
#color-picker { | |
margin-right: 20px; | |
} | |
.previous-colors { | |
display: flex; | |
flex-wrap: wrap; | |
} | |
.previous-color { | |
width: 20px; | |
height: 20px; | |
margin: 5px; | |
cursor: pointer; | |
} | |
</style> | |
</head> | |
<body> | |
<canvas id="color-picker" width="200" height="200"></canvas> | |
<div id="color-picker-container"> | |
<div class="previous-colors" id="previous-colors"></div> | |
Selected Color: <span id="selected-color">#8b8b8b</span> | |
</div> | |
<div id="grid-container"></div> | |
<script> | |
document.addEventListener("DOMContentLoaded", function () { | |
const gridContainer = document.getElementById("grid-container"); | |
const colorPickerCanvas = document.getElementById("color-picker"); | |
const selectedColorSpan = document.getElementById("selected-color"); | |
const previousColorsContainer = document.getElementById("previous-colors"); | |
const ctx = colorPickerCanvas.getContext("2d"); | |
// Initialize color picker | |
drawColorWheel(); | |
// Adjust the number of rows and columns as needed | |
const numRows = 25; | |
const numCols = 25; | |
let currentColor = "#8b8b8b"; | |
let isMouseDown = false; | |
// Create the grid | |
for (let i = 0; i < numRows; i++) { | |
for (let j = 0; j < numCols; j++) { | |
const gridSquare = document.createElement("div"); | |
gridSquare.classList.add("grid-square"); | |
gridSquare.addEventListener("mousedown", function (event) { | |
event.preventDefault(); | |
isMouseDown = true; | |
paintGridSquare(gridSquare); | |
}); | |
gridSquare.addEventListener("mousemove", function () { | |
if (isMouseDown) { | |
paintGridSquare(gridSquare); | |
} | |
}); | |
gridContainer.appendChild(gridSquare); | |
} | |
} | |
document.addEventListener("mouseup", function () { | |
isMouseDown = false; | |
}); | |
function paintGridSquare(square) { | |
square.style.backgroundColor = currentColor; | |
} | |
function drawColorWheel() { | |
const radius = colorPickerCanvas.width / 2; | |
const imageData = ctx.createImageData(colorPickerCanvas.width, colorPickerCanvas.height); | |
const data = imageData.data; | |
for (let y = -radius; y < radius; y++) { | |
for (let x = -radius; x < radius; x++) { | |
const angle = Math.atan2(y, x); | |
const distance = Math.sqrt(x * x + y * y); | |
if (distance < radius) { | |
const hue = (angle + Math.PI) / (2 * Math.PI); | |
const saturation = distance / radius; | |
const value = 1; | |
const rgb = hsvToRgb(hue, saturation, value); | |
const index = (Math.round(radius + y) * colorPickerCanvas.width + Math.round(radius + x)) * 4; | |
data[index] = rgb[0]; | |
data[index + 1] = rgb[1]; | |
data[index + 2] = rgb[2]; | |
data[index + 3] = 255; | |
} | |
} | |
} | |
ctx.putImageData(imageData, 0, 0); | |
colorPickerCanvas.addEventListener("click", function (event) { | |
const rect = colorPickerCanvas.getBoundingClientRect(); | |
const x = event.clientX - rect.left; | |
const y = event.clientY - rect.top; | |
const pixel = ctx.getImageData(x, y, 1, 1).data; | |
const clickedColor = rgbToHex(pixel[0], pixel[1], pixel[2]); | |
setCurrentColor(clickedColor); | |
}); | |
} | |
function setCurrentColor(color) { | |
currentColor = color; | |
selectedColorSpan.textContent = color; | |
addPreviousColor(color); | |
} | |
function addPreviousColor(color) { | |
const previousColorDiv = document.createElement("div"); | |
previousColorDiv.classList.add("previous-color"); | |
previousColorDiv.style.backgroundColor = color; | |
previousColorDiv.addEventListener("click", function () { | |
setCurrentColor(color); | |
}); | |
previousColorsContainer.appendChild(previousColorDiv); | |
// Keep only the last 20 colors | |
if (previousColorsContainer.children.length > 20) { | |
previousColorsContainer.removeChild(previousColorsContainer.firstChild); | |
} | |
} | |
function hsvToRgb(h, s, v) { | |
let r, g, b; | |
const i = Math.floor(h * 6); | |
const f = h * 6 - i; | |
const p = v * (1 - s); | |
const q = v * (1 - f * s); | |
const t = v * (1 - (1 - f) * s); | |
switch (i % 6) { | |
case 0: r = v; g = t; b = p; break; | |
case 1: r = q; g = v; b = p; break; | |
case 2: r = p; g = v; b = t; break; | |
case 3: r = p; g = q; b = v; break; | |
case 4: r = t; g = p; b = v; break; | |
case 5: r = v; g = p; b = q; break; | |
} | |
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)]; | |
} | |
function rgbToHex(r, g, b) { | |
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1); | |
} | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment