UNPKG

@zoom-image/core

Version:
223 lines (217 loc) 7.77 kB
'use strict'; var store = require('@namnode/store'); // src/createZoomImageHover.ts // src/imageLoader.ts var THRESHOLD = 50; var makeImageLoader = () => { const createZoomImage = (img, src, store) => { if (img.src === src) return; img.src = src; let complete = false; img.onload = () => { complete = true; store.setState({ zoomedImgStatus: "loaded" }); }; img.onerror = () => { complete = true; store.setState({ zoomedImgStatus: "error" }); }; setTimeout(() => { if (!complete) store.setState({ zoomedImgStatus: "loading" }); }, THRESHOLD); }; return { createZoomImage }; }; var imageLoader = makeImageLoader(); // src/utils.ts function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } function preventDefault(event) { event.preventDefault(); } var keySet = /* @__PURE__ */ new Set(["ArrowUp", "ArrowRight", "ArrowDown", "ArrowLeft"]); function preventDefaultForScrollKeys(event) { if (keySet.has(event.key)) { preventDefault(event); return false; } } var controller = new AbortController(); var signal = controller.signal; function disableScroll() { window.addEventListener("DOMMouseScroll", preventDefault, { signal }); window.addEventListener("wheel", preventDefault, { passive: false, signal }); window.addEventListener("touchmove", preventDefault, { passive: false, signal }); window.addEventListener("keydown", preventDefaultForScrollKeys, { signal }); } function enableScroll() { controller?.abort(); } function getSourceImage(container) { if (!container) { throw new Error("Please specify a container for the zoom image"); } const sourceImgElement = container.querySelector("img"); if (!sourceImgElement) { throw new Error("Please place an image inside the container"); } return sourceImgElement; } // src/createZoomImageHover.ts function createZoomImageHover(container, options) { const controller2 = new AbortController(); const { signal: signal2 } = controller2; const sourceImgElement = getSourceImage(container); const zoomedImgWrapper = document.createElement("div"); zoomedImgWrapper.style.overflow = "hidden"; const zoomedImg = zoomedImgWrapper.appendChild(document.createElement("img")); zoomedImg.alt = options.zoomImageProps?.alt || ""; zoomedImg.style.maxWidth = "none"; zoomedImg.style.display = "none"; const zoomLens = container.appendChild(document.createElement("div")); zoomLens.style.display = "none"; let sourceImageElementWidth = 0; let sourceImageElementHeight = 0; const finalOptions = { zoomImageSource: options.zoomImageSource || sourceImgElement.src, zoomLensClass: options.zoomLensClass || "", zoomTargetClass: options.zoomTargetClass || "", customZoom: options.customZoom, scale: options.scale || 2, zoomTarget: options.zoomTarget, zoomLensScale: options.zoomLensScale || 1, disableScrollLock: options.disableScrollLock || false }; const { scale, zoomImageSource, customZoom, zoomLensClass, zoomTarget, zoomLensScale, zoomTargetClass, disableScrollLock } = finalOptions; const store$1 = store.createStore({ zoomedImgStatus: "idle", enabled: true }); let offset = getOffset(sourceImgElement); function getOffset(element) { const elRect = element.getBoundingClientRect(); return { left: elRect.left, top: elRect.top }; } function getLimitX(value) { return sourceImageElementWidth - value; } function getLimitY(value) { return sourceImageElementHeight - value; } function zoomLensLeft(left) { const minX = zoomLens.clientWidth / 2; return clamp(left, minX, getLimitX(minX)) - minX; } function zoomLensTop(top) { const minY = zoomLens.clientHeight / 2; return clamp(top, minY, getLimitY(minY)) - minY; } function processZoom(event) { let offsetX; let offsetY; let backgroundX; let backgroundY; if (offset) { offsetX = zoomLensLeft(event.clientX - offset.left); offsetY = zoomLensTop(event.clientY - offset.top); backgroundX = offsetX * scale / zoomLensScale; backgroundY = offsetY * scale / zoomLensScale; zoomedImg.style.transform = "translate(" + -backgroundX + "px," + -backgroundY + "px)"; zoomLens.style.cssText += "transform:translate(" + offsetX + "px," + offsetY + "px);"; } } async function handlePointerEnter() { imageLoader.createZoomImage(zoomedImg, zoomImageSource, store$1); zoomedImg.style.display = "block"; zoomLens.style.display = "block"; if (zoomTargetClass) { const classes = zoomTargetClass.split(" "); classes.forEach((className) => zoomTarget.classList.add(className)); } if (!disableScrollLock) disableScroll(); } function handlePointerLeave() { zoomedImg.style.display = "none"; zoomLens.style.display = "none"; if (zoomTargetClass) { const classes = zoomTargetClass.split(" "); classes.forEach((className) => zoomTarget.classList.remove(className)); } if (!disableScrollLock) enableScroll(); } function handleScroll() { offset = getOffset(sourceImgElement); } async function setup() { if (zoomLensClass) { zoomLens.className = zoomLensClass; } else { zoomLens.style.background = "rgba(238, 130, 238, 0.5)"; } container.addEventListener("pointerdown", processZoom, { signal: signal2 }); container.addEventListener("pointermove", processZoom, { signal: signal2 }); container.addEventListener("pointerenter", handlePointerEnter, { signal: signal2 }); container.addEventListener("pointerleave", handlePointerLeave, { signal: signal2 }); window.addEventListener("scroll", handleScroll, { signal: signal2 }); container.addEventListener("touchend", enableScroll, { signal: signal2 }); zoomTarget.appendChild(zoomedImgWrapper); await new Promise((resolve) => setTimeout(resolve, 1)); const containerRect = container.getBoundingClientRect(); sourceImageElementWidth = containerRect.width; sourceImageElementHeight = containerRect.height; if (customZoom) { zoomedImgWrapper.style.width = customZoom.width + "px"; zoomedImgWrapper.style.height = customZoom.height + "px"; } else { zoomedImgWrapper.style.width = sourceImageElementWidth + "px"; zoomedImgWrapper.style.height = sourceImageElementHeight + "px"; } zoomedImg.width = sourceImageElementWidth * scale / zoomLensScale; zoomedImg.height = sourceImageElementHeight * scale / zoomLensScale; const sourceImageRect = sourceImgElement.getBoundingClientRect(); const fromLeft = sourceImageRect.left - containerRect.left; const fromTop = sourceImageRect.top - containerRect.top; zoomTarget.style.pointerEvents = "none"; zoomLens.style.position = "absolute"; zoomLens.style.left = fromLeft + "px"; zoomLens.style.top = fromTop + "px"; zoomLens.style.width = customZoom.width / scale * zoomLensScale + "px"; zoomLens.style.height = customZoom.height / scale * zoomLensScale + "px"; } setup(); return { cleanup: () => { controller2.abort(); container.contains(zoomLens) && container.removeChild(zoomLens); if (zoomTarget && zoomTarget.contains(zoomedImgWrapper)) { zoomTarget.removeChild(zoomedImgWrapper); return; } container.contains(zoomedImgWrapper) && container.removeChild(zoomedImgWrapper); }, subscribe: store$1.subscribe, getState: store$1.getState, setState: (newState) => { store$1.setState(newState); } }; } exports.createZoomImageHover = createZoomImageHover; //# sourceMappingURL=out.js.map //# sourceMappingURL=createZoomImageHover.js.map