@zoom-image/core
Version:
A core implementation of zoom image
1 lines • 5.88 kB
Source Map (JSON)
{"version":3,"sources":["../src/createZoomImageClick.ts"],"names":[],"mappings":";;;;;;;;;;;AAAA,SAAS,mBAAmB;AAkBrB,SAAS,qBAAqB,WAAwB,UAAiC,CAAC,GAAG;AAChG,QAAM,mBAAmB,eAAe,SAAS;AACjD,QAAM,eAAwE;AAAA,IAC5E,YAAY,QAAQ,cAAc;AAAA,IAClC,iBAAiB,QAAQ,mBAAmB,iBAAiB;AAAA,IAC7D,mBAAmB,QAAQ,qBAAqB;AAAA,EAClD;AAEA,QAAM,EAAE,YAAY,iBAAiB,kBAAkB,IAAI;AAE3D,MAAI,WAAW;AAEf,QAAM,QAAQ,YAAiC;AAAA,IAC7C,iBAAiB;AAAA,EACnB,CAAC;AAED,QAAM,iBAAiB,iBAAiB,cAAc;AACtD,QAAM,kBAAkB,iBAAiB,eAAe;AACxD,QAAM,YAAY,UAAU,YAAY,SAAS,cAAc,KAAK,CAAC;AACrE,YAAU,MAAM,QAAQ,gBAAgB,OAAO;AAC/C,YAAU,MAAM,WAAW;AAC3B,YAAU,MAAM,UAAU;AAC1B,YAAU,MAAM,QAAQ,GAAG,cAAc;AACzC,YAAU,MAAM,SAAS,GAAG,eAAe;AAC3C,YAAU,MAAM,WAAW;AAC3B,YAAU,MAAM,MAAM;AACtB,YAAU,MAAM,OAAO;AAEvB,WAAS,kBAAkB,OAAqB;AAC9C,QAAI,CAAC,UAAU;AACb;AAAA,IACF;AAEA,gBAAY,KAAK;AAAA,EACnB;AAEA,QAAM,qBAAqB,CAAC,iBAAyB;AACnD,UAAM,QAAQ,UAAU;AACxB,QAAI,eAAe;AAAG,aAAO;AAC7B,QAAI,eAAe,QAAQ,aAAa;AAAO,aAAO,CAAC,SAAS,aAAa;AAC7E,WAAO;AAAA,EACT;AAEA,QAAM,qBAAqB,CAAC,iBAAyB;AACnD,UAAM,SAAS,UAAU;AACzB,QAAI,eAAe;AAAG,aAAO;AAC7B,QAAI,eAAe,SAAS,aAAa;AAAQ,aAAO,CAAC,UAAU,aAAa;AAChF,WAAO;AAAA,EACT;AAEA,WAAS,YAAY,OAAqB;AACxC,cAAU,MAAM,UAAU;AAC1B,gBAAY,gBAAgB,WAAW,iBAAiB,KAAK;AAE7D,UAAM,gBAAgB,UAAU,sBAAsB;AACtD,UAAM,aAAa,MAAM,UAAU,cAAc;AACjD,UAAM,aAAa,MAAM,UAAU,cAAc;AAEjD,UAAM,mBAAmB,mBAAmB,CAAC,aAAa,aAAa,UAAU;AACjF,UAAM,mBAAmB,mBAAmB,CAAC,aAAa,aAAa,UAAU;AAEjF,cAAU,MAAM,YAAY,aAAa,gBAAgB,OAAO,gBAAgB;AAAA,EAClF;AAEA,WAAS,kBAAkB,OAAqB;AAC9C,QAAI,UAAU;AACZ,iBAAW;AACX,gBAAU,MAAM,UAAU;AAC1B;AAAA,IACF;AAEA,gBAAY,KAAK;AACjB,eAAW;AAAA,EACb;AAEA,QAAM,aAAa,IAAI,gBAAgB;AACvC,QAAM,EAAE,OAAO,IAAI;AACnB,YAAU,iBAAiB,eAAe,mBAAmB,EAAE,OAAO,CAAC;AACvE,YAAU,iBAAiB,gBAAgB,oBAAoB,OAAO,eAAe,EAAE,OAAO,CAAC;AAC/F,YAAU,iBAAiB,gBAAgB,oBAAoB,OAAO,cAAc,EAAE,OAAO,CAAC;AAC9F,YAAU,iBAAiB,eAAe,mBAAmB,EAAE,OAAO,CAAC;AACvE,YAAU,iBAAiB,YAAY,cAAc,EAAE,OAAO,CAAC;AAE/D,SAAO;AAAA,IACL,SAAS,MAAM;AACb,iBAAW,MAAM;AACjB,gBAAU,SAAS,SAAS,KAAK,UAAU,YAAY,SAAS;AAChE,YAAM,QAAQ;AAAA,IAChB;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,UAAU,MAAM;AAAA,EAClB;AACF","sourcesContent":["import { createStore } from \"@namnode/store\"\nimport { imageLoader } from \"./imageLoader\"\nimport { ZoomedImgStatus } from \"./types\"\nimport { disableScroll, enableScroll, getSourceImage, noop } from \"./utils\"\n\nexport type ZoomImageClickOptions = {\n zoomFactor?: number\n zoomImageSource?: string\n disableScrollLock?: boolean\n zoomImageProps?: {\n alt?: string\n }\n}\n\nexport type ZoomImageClickState = {\n zoomedImgStatus: ZoomedImgStatus\n}\n\nexport function createZoomImageClick(container: HTMLElement, options: ZoomImageClickOptions = {}) {\n const sourceImgElement = getSourceImage(container)\n const finalOptions: Omit<Required<ZoomImageClickOptions>, \"zoomImageProps\"> = {\n zoomFactor: options.zoomFactor ?? 4,\n zoomImageSource: options.zoomImageSource ?? sourceImgElement.src,\n disableScrollLock: options.disableScrollLock ?? false,\n }\n\n const { zoomFactor, zoomImageSource, disableScrollLock } = finalOptions\n\n let isOnMove = false\n\n const store = createStore<ZoomImageClickState>({\n zoomedImgStatus: \"idle\",\n })\n\n const zoomedImgWidth = sourceImgElement.clientWidth * zoomFactor\n const zoomedImgHeight = sourceImgElement.clientHeight * zoomFactor\n const zoomedImg = container.appendChild(document.createElement(\"img\"))\n zoomedImg.alt = options.zoomImageProps?.alt || \"\"\n zoomedImg.style.maxWidth = \"none\"\n zoomedImg.style.display = \"none\"\n zoomedImg.style.width = `${zoomedImgWidth}px`\n zoomedImg.style.height = `${zoomedImgHeight}px`\n zoomedImg.style.position = \"absolute\"\n zoomedImg.style.top = \"0\"\n zoomedImg.style.left = \"0\"\n\n function handlePointerMove(event: PointerEvent) {\n if (!isOnMove) {\n return\n }\n\n processZoom(event)\n }\n\n const calculatePositionX = (newPositionX: number) => {\n const width = container.clientWidth\n if (newPositionX > 0) return 0\n if (newPositionX + width * zoomFactor < width) return -width * (zoomFactor - 1)\n return newPositionX\n }\n\n const calculatePositionY = (newPositionY: number) => {\n const height = container.clientHeight\n if (newPositionY > 0) return 0\n if (newPositionY + height * zoomFactor < height) return -height * (zoomFactor - 1)\n return newPositionY\n }\n\n function processZoom(event: PointerEvent) {\n zoomedImg.style.display = \"block\"\n imageLoader.createZoomImage(zoomedImg, zoomImageSource, store)\n\n const containerRect = container.getBoundingClientRect()\n const zoomPointX = event.clientX - containerRect.left\n const zoomPointY = event.clientY - containerRect.top\n\n const currentPositionX = calculatePositionX(-zoomPointX * zoomFactor + zoomPointX)\n const currentPositionY = calculatePositionY(-zoomPointY * zoomFactor + zoomPointY)\n\n zoomedImg.style.transform = `translate(${currentPositionX}px, ${currentPositionY}px)`\n }\n\n function handlePointerDown(event: PointerEvent) {\n if (isOnMove) {\n isOnMove = false\n zoomedImg.style.display = \"none\"\n return\n }\n\n processZoom(event)\n isOnMove = true\n }\n\n const controller = new AbortController()\n const { signal } = controller\n container.addEventListener(\"pointerdown\", handlePointerDown, { signal })\n container.addEventListener(\"pointerenter\", disableScrollLock ? noop : disableScroll, { signal })\n container.addEventListener(\"pointerleave\", disableScrollLock ? noop : enableScroll, { signal })\n container.addEventListener(\"pointermove\", handlePointerMove, { signal })\n container.addEventListener(\"touchend\", enableScroll, { signal })\n\n return {\n cleanup: () => {\n controller.abort()\n container.contains(zoomedImg) && container.removeChild(zoomedImg)\n store.cleanup()\n },\n subscribe: store.subscribe,\n getState: store.getState,\n }\n}\n"]}