Skip to main content

Overview

createZoomImageClick creates a click-activated zoom effect. Users click once to activate zoom mode, move the pointer to pan around the magnified image, and click again to deactivate. The zoomed image is rendered as an overlay on the original image.

Function Signature

function createZoomImageClick(
  container: HTMLElement,
  options?: ZoomImageClickOptions
): {
  cleanup: () => void
  subscribe: (listener: Listener) => () => void
  getState: () => ZoomImageClickState
}

Parameters

container
HTMLElement
required
The HTML element that contains the image to be zoomed. The function will automatically find the first <img> element inside this container.
options
ZoomImageClickOptions
Configuration options for the click zoom behavior.
options.zoomFactor
number
default:"4"
The magnification factor for the zoomed image. A value of 4 means the image will be displayed at 4x its original size.
options.zoomImageSource
string
The URL of a higher-resolution image to display in the zoom view. Defaults to the source image’s src attribute.
options.disableScrollLock
boolean
default:"false"
If true, page scrolling will not be locked when zoom is active. By default, scrolling is disabled during zoom to prevent accidental page navigation.
options.zoomImageProps
object
Additional properties for the zoomed image element.
options.zoomImageProps.alt
string
Alt text for the zoomed image element.

Return Value

Returns an object with the following methods:
cleanup
() => void
Removes all event listeners and the zoomed image element. Call this when the component unmounts or when zoom functionality is no longer needed.
subscribe
(listener: Listener) => () => void
Subscribe to state changes. The listener is called when the zoomed image loading status changes. Returns an unsubscribe function.
type Listener = (state: ZoomImageClickState, prevState: ZoomImageClickState) => void
getState
() => ZoomImageClickState
Get the current state including the zoomed image loading status.

State Types

ZoomImageClickState

type ZoomImageClickState = {
  zoomedImgStatus: ZoomedImgStatus  // "idle" | "loading" | "loaded" | "error"
}

ZoomedImgStatus

type ZoomedImgStatus = "idle" | "loading" | "loaded" | "error"

Usage Examples

Basic Usage

import { createZoomImageClick } from '@zoom-image/core'

const container = document.getElementById('image-container')
const { cleanup } = createZoomImageClick(container)

// Call cleanup when done
cleanup()

With Custom Options

const { cleanup } = createZoomImageClick(container, {
  zoomFactor: 3,
  zoomImageSource: '/images/product-large.jpg'
})

With High-Resolution Image

const { cleanup } = createZoomImageClick(container, {
  zoomFactor: 5,
  zoomImageSource: '/images/high-resolution.jpg',
  disableScrollLock: false,
  zoomImageProps: {
    alt: 'Zoomed product view'
  }
})

Subscribe to Loading State

const { cleanup, subscribe, getState } = createZoomImageClick(container, {
  zoomImageSource: '/images/large.jpg'
})

const unsubscribe = subscribe((state, prevState) => {
  if (state.zoomedImgStatus !== prevState.zoomedImgStatus) {
    console.log('Status changed:', prevState.zoomedImgStatus, '->', state.zoomedImgStatus)
  }

  switch (state.zoomedImgStatus) {
    case 'idle':
      console.log('Zoom not activated')
      break
    case 'loading':
      console.log('Loading high-res image...')
      break
    case 'loaded':
      console.log('Image ready for zooming')
      break
    case 'error':
      console.error('Failed to load zoom image')
      break
  }
})

// Check current state
const state = getState()
console.log('Current status:', state.zoomedImgStatus)

// Cleanup
unsubscribe()
cleanup()

With Loading Indicator

<div id="image-container" style="position: relative;">
  <img src="product.jpg" alt="Product" />
  <div id="loading" style="display: none;">Loading...</div>
</div>
const container = document.getElementById('image-container')
const loading = document.getElementById('loading')

const { cleanup, subscribe } = createZoomImageClick(container, {
  zoomImageSource: '/images/product-hd.jpg'
})

subscribe((state) => {
  loading.style.display = state.zoomedImgStatus === 'loading' ? 'block' : 'none'
})

Product Detail Page

<div class="product-detail">
  <div id="product-image" style="width: 600px; height: 600px; position: relative; cursor: zoom-in;">
    <img src="product-thumb.jpg" alt="Product" style="width: 100%; height: 100%; object-fit: cover;" />
  </div>
  <p class="hint">Click to zoom, move to pan, click again to exit</p>
</div>
const container = document.getElementById('product-image')

const { cleanup } = createZoomImageClick(container, {
  zoomFactor: 4,
  zoomImageSource: 'product-full.jpg',
  disableScrollLock: false
})

// Update cursor style based on zoom state
let isZoomed = false
container.addEventListener('pointerdown', () => {
  isZoomed = !isZoomed
  container.style.cursor = isZoomed ? 'zoom-out' : 'zoom-in'
})

Enable/Disable Scroll Lock

// Keep page scrolling enabled during zoom
const { cleanup } = createZoomImageClick(container, {
  disableScrollLock: true
})

// Default behavior - disable scrolling during zoom
const { cleanup } = createZoomImageClick(container, {
  disableScrollLock: false  // or omit this option
})

Handle Loading Errors

const { cleanup, subscribe } = createZoomImageClick(container, {
  zoomImageSource: '/images/might-not-exist.jpg'
})

subscribe((state) => {
  if (state.zoomedImgStatus === 'error') {
    console.error('Failed to load zoom image')
    // Fallback: use original image
    // or show an error message to user
  }
})

Features

  • Click to activate: Click once to enter zoom mode, click again to exit
  • Panning: Move pointer while zoomed to pan around the magnified image
  • In-place zoom: Magnified image overlays the original
  • Lazy loading: High-resolution image loads only when first clicked
  • Loading states: Track image loading progress
  • Scroll lock: Optionally disable page scrolling during zoom
  • Auto-cleanup: Properly removes all elements and event listeners
  • Touch support: Works with mouse, touch, and pen inputs

Behavior

  1. First click: Activates zoom mode, loads and displays the magnified image at the click position
  2. Pointer move: While zoomed, moving the pointer pans the magnified view
  3. Second click: Deactivates zoom mode and hides the magnified image
  4. Boundary detection: Automatically constrains panning to keep the image within view
  5. Scroll control: By default, page scrolling is disabled on pointer enter and re-enabled on pointer leave

Comparison with createZoomImageMove

FeaturecreateZoomImageClickcreateZoomImageMove
ActivationClick to toggleHover/enter to activate
DeactivationClick againLeave container
Use caseDeliberate inspectionQuick preview
User controlExplicit on/offAutomatic

Source Reference

Implementation: /packages/core/src/createZoomImageClick.ts:19

Build docs developers (and LLMs) love