mirror of
https://github.com/imfing/hextra.git
synced 2025-09-15 12:01:59 -04:00
feat(image-zoom): add minimal image zoom functionality
- Introduced CSS for image zoom overlay and image styling. - Implemented JavaScript for handling image zoom interactions, including overlay creation and close functionality. - Updated configuration to enable image zoom feature in site parameters. - Added partial for including image zoom assets in the layout.
This commit is contained in:
76
assets/js/image-zoom.js
Normal file
76
assets/js/image-zoom.js
Normal file
@@ -0,0 +1,76 @@
|
||||
// Minimal, dependency-free image zoom for Hextra
|
||||
// - Activates on images inside `.content`
|
||||
// - Close on overlay click or Escape
|
||||
// - Opt-out with `data-no-zoom` on <img>
|
||||
|
||||
(function () {
|
||||
function ready(fn) {
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", fn, { once: true });
|
||||
} else {
|
||||
fn();
|
||||
}
|
||||
}
|
||||
|
||||
function createOverlay(src, alt) {
|
||||
const overlay = document.createElement("div");
|
||||
overlay.className = "hextra-zoom-image-overlay";
|
||||
overlay.setAttribute("role", "dialog");
|
||||
overlay.setAttribute("aria-modal", "true");
|
||||
|
||||
const img = document.createElement("img");
|
||||
img.className = "hextra-zoom-image";
|
||||
img.src = src;
|
||||
if (alt) img.alt = alt;
|
||||
|
||||
overlay.appendChild(img);
|
||||
|
||||
function close() {
|
||||
overlay.classList.remove("show");
|
||||
document.documentElement.style.removeProperty("overflow");
|
||||
window.removeEventListener("keydown", onKeyDown, true);
|
||||
overlay.addEventListener(
|
||||
"transitionend",
|
||||
() => overlay.remove(),
|
||||
{ once: true }
|
||||
);
|
||||
}
|
||||
|
||||
function onKeyDown(e) {
|
||||
if (e.key === "Escape") close();
|
||||
}
|
||||
|
||||
overlay.addEventListener("click", close, { once: true });
|
||||
window.addEventListener("keydown", onKeyDown, true);
|
||||
|
||||
document.body.appendChild(overlay);
|
||||
// lock scroll
|
||||
document.documentElement.style.overflow = "hidden";
|
||||
|
||||
// trigger fade-in
|
||||
requestAnimationFrame(() => overlay.classList.add("show"));
|
||||
}
|
||||
|
||||
ready(function () {
|
||||
const container = document.querySelector(".content");
|
||||
if (!container) return;
|
||||
|
||||
container.addEventListener(
|
||||
"click",
|
||||
function (e) {
|
||||
const target = e.target;
|
||||
if (!(target instanceof HTMLImageElement)) return;
|
||||
if (target.dataset.noZoom === "" || target.dataset.noZoom === "true") return;
|
||||
|
||||
// avoid following parent links when zooming
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const src = target.currentSrc || target.src;
|
||||
if (!src) return;
|
||||
createOverlay(src, target.alt || "");
|
||||
},
|
||||
true
|
||||
);
|
||||
});
|
||||
})();
|
Reference in New Issue
Block a user