Caps-Server/Public/grid.js
2022-12-20 00:56:56 +01:00

191 lines
5.5 KiB
JavaScript

const capImageSize = 50;
const halfCapImageSize = capImageSize / 2;
const numberOfCaps = 1875;
const numberOfColumns = 40;
const numberOfRows = Math.ceil(numberOfCaps / numberOfColumns);
const effectiveHeight = Math.ceil(capImageSize*Math.cos(Math.PI/6));
function sourcePath(capId) {
return "thumbnails/" + `${capId}`.padStart(4, '0') + '.jpg'
}
function createImage(position) {
return '<img src="' + sourcePath(position) + '" loading="lazy"/>'
};
function setCapImageAtPosition(capId, position) {
elements[position].src = sourcePath(capId);
capPositions[position] = capId;
}
function getCapIdAtPosition(position) {
return capPositions[position];
}
const imageCanvas = document.getElementById("image-canvas");
var capPositions = Array.from(
{length: numberOfCaps},
(_, index) => index + 1
);
imageCanvas.innerHTML += capPositions.map(createImage).join("");
var selectedPosition = null;
const elements = imageCanvas.getElementsByTagName("img");
const selectedCapCircle = document.getElementById("selected-cap-circle");
imageCanvas.addEventListener("click", function(event) {
const yOffset = 50;
const xPosition = event.clientX - imageCanvas.getBoundingClientRect().left;
const yPosition = event.clientY - imageCanvas.getBoundingClientRect().top - yOffset;
var row = Math.floor(yPosition / effectiveHeight);
var rowIsEven = (row % 2 == 0)
const adjustedX = rowIsEven ? xPosition - halfCapImageSize : xPosition;
var column = Math.floor(adjustedX / capImageSize);
const rowRemainder = yPosition % effectiveHeight - halfCapImageSize;
const columnRemainder = adjustedX % capImageSize - halfCapImageSize;
const distanceToCenter = Math.sqrt(rowRemainder**2 + columnRemainder**2);
if (distanceToCenter > halfCapImageSize && rowRemainder < 6 - halfCapImageSize) {
// Move to the top left cap
row -= 1;
if (!rowIsEven && (columnRemainder < 0)) {
// Move to the top right cap
column -= 1;
}
if (rowIsEven && (columnRemainder > 0)) {
// Move to the top left cap
column += 1;
}
rowIsEven = !rowIsEven
}
if (row < 0 || row >= numberOfRows) {
return;
}
if (column < 0 || column >= numberOfColumns) {
return;
}
const currentPosition = row * numberOfColumns + column;
if (selectedPosition === null) {
selectedPosition = currentPosition;
const circlePositionX = rowIsEven ? column * capImageSize + halfCapImageSize : column * capImageSize;
const circlePositionY = row * effectiveHeight + yOffset;
selectedCapCircle.style.left = circlePositionX + "px";
selectedCapCircle.style.top = circlePositionY + "px";
selectedCapCircle.style.display = "block";
return;
}
selectedCapCircle.style.display = "none";
if (currentPosition === selectedPosition) {
selectedPosition = null;
return;
}
// Switch cap images
const currentCapId = getCapIdAtPosition(currentPosition);
const selectedCapId = getCapIdAtPosition(selectedPosition);
setCapImageAtPosition(selectedCapId, currentPosition);
setCapImageAtPosition(currentCapId, selectedPosition);
selectedPosition = null;
});
function averageColor(imageElement) {
var canvas = document.createElement('canvas');
var context = canvas.getContext && canvas.getContext('2d');
if (!context) {
return { r: 255, g: 0, b: 0 };
}
// Set the height and width equal
// to that of the canvas and the image
var height = canvas.height =
imageElement.naturalHeight ||
imageElement.offsetHeight ||
imageElement.height;
var width = canvas.width =
imageElement.naturalWidth ||
imageElement.offsetWidth ||
imageElement.width;
// Draw the image to the canvas
context.drawImage(imageElement, 0, 0);
// Get the data of the image
try {
var imgData = context.getImageData(0, 0, width, height);
} catch(e) {
/* security error, img on diff domain */alert('x');
return { r: 255, g: 0, b: 0 };
}
// Get the length of image data object
var length = imgData.data.length;
const pixelCount = height * width;
const halfX = width / 2;
const halfY = height / 2;
var rgb = { r: 0, g: 0, b: 0 };
var count = 0;
for (var i = 0; i < pixelCount; i += 1) {
// Exclude everything outside of circle
const x = i % width - halfX;
const y = Math.floor(i / width) - halfY;
const distanceToCenter = Math.sqrt(x**2 + y**2);
if (distanceToCenter > halfY) {
continue;
}
// Sum all values of the colour
const offset = 4 * i;
rgb.r += imgData.data[offset];
rgb.g += imgData.data[offset + 1];
rgb.b += imgData.data[offset + 2];
count += 1;
}
// Find the averages
rgb.r = Math.floor(rgb.r / count);
rgb.g = Math.floor(rgb.g / count);
rgb.b = Math.floor(rgb.b / count);
return rgb;
}
for (let i = 0; i < capPositions.length; i += 1) {
const element = elements[i];
element.onload = function() {
const rgb = averageColor(element);
const color = `rgb(${rgb.r},${rgb.g},${rgb.b})`;
element.style.backgroundColor = color;
}
}
var showColors = false;
function toggleColors() {
showColors = !showColors;
const padding = showColors ? "50px" : "0px";
for (let i = 0; i < capPositions.length; i += 1) {
elements[i].style.paddingLeft = padding;
}
}