refactoring
This commit is contained in:
176
app/ui-tarot-lightbox.js
Normal file
176
app/ui-tarot-lightbox.js
Normal file
@@ -0,0 +1,176 @@
|
||||
(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
|
||||
};
|
||||
})();
|
||||
Reference in New Issue
Block a user