176 lines
4.5 KiB
JavaScript
176 lines
4.5 KiB
JavaScript
(function () {
|
|
"use strict";
|
|
|
|
let overlayEl = null;
|
|
let imageEl = null;
|
|
let zoomed = false;
|
|
|
|
const LIGHTBOX_ZOOM_SCALE = 6.66;
|
|
|
|
function resetZoom() {
|
|
if (!imageEl) {
|
|
return;
|
|
}
|
|
|
|
zoomed = false;
|
|
imageEl.style.transform = "scale(1)";
|
|
imageEl.style.transformOrigin = "center center";
|
|
imageEl.style.cursor = "zoom-in";
|
|
}
|
|
|
|
function updateZoomOrigin(clientX, clientY) {
|
|
if (!zoomed || !imageEl) {
|
|
return;
|
|
}
|
|
|
|
const rect = imageEl.getBoundingClientRect();
|
|
if (!rect.width || !rect.height) {
|
|
return;
|
|
}
|
|
|
|
const x = Math.min(100, Math.max(0, ((clientX - rect.left) / rect.width) * 100));
|
|
const y = Math.min(100, Math.max(0, ((clientY - rect.top) / rect.height) * 100));
|
|
imageEl.style.transformOrigin = `${x}% ${y}%`;
|
|
}
|
|
|
|
function isPointOnCard(clientX, clientY) {
|
|
if (!imageEl) {
|
|
return false;
|
|
}
|
|
|
|
const rect = imageEl.getBoundingClientRect();
|
|
const naturalWidth = imageEl.naturalWidth;
|
|
const naturalHeight = imageEl.naturalHeight;
|
|
|
|
if (!rect.width || !rect.height || !naturalWidth || !naturalHeight) {
|
|
return true;
|
|
}
|
|
|
|
const frameAspect = rect.width / rect.height;
|
|
const imageAspect = naturalWidth / naturalHeight;
|
|
|
|
let renderWidth = rect.width;
|
|
let renderHeight = rect.height;
|
|
if (imageAspect > frameAspect) {
|
|
renderHeight = rect.width / imageAspect;
|
|
} else {
|
|
renderWidth = rect.height * imageAspect;
|
|
}
|
|
|
|
const left = rect.left + (rect.width - renderWidth) / 2;
|
|
const top = rect.top + (rect.height - renderHeight) / 2;
|
|
const right = left + renderWidth;
|
|
const bottom = top + renderHeight;
|
|
|
|
return clientX >= left && clientX <= right && clientY >= top && clientY <= bottom;
|
|
}
|
|
|
|
function ensure() {
|
|
if (overlayEl && imageEl) {
|
|
return;
|
|
}
|
|
|
|
overlayEl = document.createElement("div");
|
|
overlayEl.setAttribute("aria-hidden", "true");
|
|
overlayEl.style.position = "fixed";
|
|
overlayEl.style.inset = "0";
|
|
overlayEl.style.background = "rgba(0, 0, 0, 0.82)";
|
|
overlayEl.style.display = "none";
|
|
overlayEl.style.alignItems = "center";
|
|
overlayEl.style.justifyContent = "center";
|
|
overlayEl.style.zIndex = "9999";
|
|
overlayEl.style.padding = "0";
|
|
|
|
imageEl = document.createElement("img");
|
|
imageEl.alt = "Tarot card enlarged image";
|
|
imageEl.style.maxWidth = "100vw";
|
|
imageEl.style.maxHeight = "100vh";
|
|
imageEl.style.width = "100vw";
|
|
imageEl.style.height = "100vh";
|
|
imageEl.style.objectFit = "contain";
|
|
imageEl.style.borderRadius = "0";
|
|
imageEl.style.boxShadow = "none";
|
|
imageEl.style.border = "none";
|
|
imageEl.style.cursor = "zoom-in";
|
|
imageEl.style.transform = "scale(1)";
|
|
imageEl.style.transformOrigin = "center center";
|
|
imageEl.style.transition = "transform 120ms ease-out";
|
|
imageEl.style.userSelect = "none";
|
|
|
|
overlayEl.appendChild(imageEl);
|
|
|
|
const close = () => {
|
|
if (!overlayEl || !imageEl) {
|
|
return;
|
|
}
|
|
overlayEl.style.display = "none";
|
|
overlayEl.setAttribute("aria-hidden", "true");
|
|
imageEl.removeAttribute("src");
|
|
resetZoom();
|
|
};
|
|
|
|
overlayEl.addEventListener("click", (event) => {
|
|
if (event.target === overlayEl) {
|
|
close();
|
|
}
|
|
});
|
|
|
|
imageEl.addEventListener("click", (event) => {
|
|
event.stopPropagation();
|
|
if (!isPointOnCard(event.clientX, event.clientY)) {
|
|
close();
|
|
return;
|
|
}
|
|
|
|
if (!zoomed) {
|
|
zoomed = true;
|
|
imageEl.style.transform = `scale(${LIGHTBOX_ZOOM_SCALE})`;
|
|
imageEl.style.cursor = "zoom-out";
|
|
updateZoomOrigin(event.clientX, event.clientY);
|
|
return;
|
|
}
|
|
|
|
resetZoom();
|
|
});
|
|
|
|
imageEl.addEventListener("mousemove", (event) => {
|
|
updateZoomOrigin(event.clientX, event.clientY);
|
|
});
|
|
|
|
imageEl.addEventListener("mouseleave", () => {
|
|
if (zoomed) {
|
|
imageEl.style.transformOrigin = "center center";
|
|
}
|
|
});
|
|
|
|
document.addEventListener("keydown", (event) => {
|
|
if (event.key === "Escape") {
|
|
close();
|
|
}
|
|
});
|
|
|
|
document.body.appendChild(overlayEl);
|
|
}
|
|
|
|
function open(src, altText) {
|
|
if (!src) {
|
|
return;
|
|
}
|
|
|
|
ensure();
|
|
if (!overlayEl || !imageEl) {
|
|
return;
|
|
}
|
|
|
|
imageEl.src = src;
|
|
imageEl.alt = altText || "Tarot card enlarged image";
|
|
resetZoom();
|
|
overlayEl.style.display = "flex";
|
|
overlayEl.setAttribute("aria-hidden", "false");
|
|
}
|
|
|
|
window.TarotUiLightbox = {
|
|
...(window.TarotUiLightbox || {}),
|
|
open
|
|
};
|
|
})(); |