Skip to main content
The React adapter provides hooks that wrap the core zoom-image functionality for seamless integration with React applications.

Installation

npm install @zoom-image/react

Available Hooks

The React adapter exports four hooks, one for each zoom mode:
  • useZoomImageWheel - Zoom with mouse wheel/pinch gestures
  • useZoomImageHover - Zoom on hover with a separate zoom target
  • useZoomImageMove - Zoom follows mouse/touch movement
  • useZoomImageClick - Toggle zoom on click

Hook Return Values

Each hook returns an object with:
  • createZoomImage - Function to initialize zoom on a container element
  • zoomImageState - Current state object (varies by zoom mode)
  • setZoomImageState - Function to update state (available for wheel and hover modes)

Wheel Zoom

Zoom in and out using the mouse wheel or pinch gestures. Supports programmatic zoom control, rotation, and image cropping.

Basic Example

import { useZoomImageWheel } from "@zoom-image/react"
import { useEffect, useRef } from "react"

function WheelZoomImage() {
  const containerRef = useRef<HTMLDivElement>(null)
  const { createZoomImage, zoomImageState } = useZoomImageWheel()

  useEffect(() => {
    if (containerRef.current) {
      createZoomImage(containerRef.current)
    }
  }, [])

  return (
    <div>
      <p>Current zoom: {Math.round(zoomImageState.currentZoom * 100)}%</p>
      <div ref={containerRef} className="h-[300px] w-[200px]">
        <img className="h-full w-full" src="/image.jpg" alt="Zoomable" />
      </div>
    </div>
  )
}

Complete Example with Controls

import { useZoomImageWheel } from "@zoom-image/react"
import { cropImage } from "@zoom-image/core"
import { useEffect, useRef, useState } from "react"

function AdvancedWheelZoom() {
  const containerRef = useRef<HTMLDivElement>(null)
  const [croppedImage, setCroppedImage] = useState<string | null>(null)
  
  const {
    createZoomImage,
    zoomImageState,
    setZoomImageState,
  } = useZoomImageWheel()

  useEffect(() => {
    if (containerRef.current) {
      createZoomImage(containerRef.current)
    }
  }, [])

  const zoomIn = () => {
    setZoomImageState({
      currentZoom: zoomImageState.currentZoom + 0.5,
    })
  }

  const zoomOut = () => {
    setZoomImageState({
      currentZoom: zoomImageState.currentZoom - 0.5,
    })
  }

  const rotate = () => {
    setZoomImageState({
      currentRotation: zoomImageState.currentRotation + 90,
    })
  }

  const handleCrop = async () => {
    const result = await cropImage({
      currentZoom: zoomImageState.currentZoom,
      image: containerRef.current?.querySelector('img') as HTMLImageElement,
      positionX: zoomImageState.currentPositionX,
      positionY: zoomImageState.currentPositionY,
      rotation: zoomImageState.currentRotation,
    })
    setCroppedImage(result)
  }

  return (
    <div>
      <div className="flex gap-4">
        <div ref={containerRef} className="h-[300px] w-[200px]">
          <img className="h-full w-full" src="/image.jpg" alt="Zoomable" />
        </div>
        {croppedImage && (
          <img src={croppedImage} alt="Cropped" className="h-[300px] w-[200px]" />
        )}
      </div>
      
      <div className="flex gap-2 mt-4">
        <button onClick={zoomIn}>Zoom In</button>
        <button onClick={zoomOut}>Zoom Out</button>
        <button onClick={rotate}>Rotate</button>
        <button onClick={handleCrop}>Crop Image</button>
      </div>
    </div>
  )
}

State Properties

  • currentZoom: number - Current zoom level (1 = 100%)
  • enable: boolean - Whether zoom is enabled
  • currentPositionX: number - X position offset
  • currentPositionY: number - Y position offset
  • currentRotation: number - Rotation angle in degrees

Hover Zoom

Display a zoomed version in a separate container when hovering over the image.

Basic Example

import { useZoomImageHover } from "@zoom-image/react"
import { useEffect, useRef } from "react"

function HoverZoomImage() {
  const containerRef = useRef<HTMLDivElement>(null)
  const zoomTargetRef = useRef<HTMLDivElement>(null)
  const { createZoomImage } = useZoomImageHover()

  useEffect(() => {
    if (containerRef.current && zoomTargetRef.current) {
      createZoomImage(containerRef.current, {
        zoomImageSource: "/image-large.jpg",
        customZoom: { width: 300, height: 500 },
        zoomTarget: zoomTargetRef.current,
        scale: 2,
      })
    }
  }, [])

  return (
    <div className="relative flex">
      <div ref={containerRef} className="h-[300px] w-[200px]">
        <img className="h-full w-full" src="/image.jpg" alt="Hover to zoom" />
      </div>
      <div ref={zoomTargetRef} className="absolute left-[350px]" />
    </div>
  )
}

State Properties

  • enabled: boolean - Whether hover is active
  • zoomedImgStatus: string - Loading status (“idle” | “loading” | “loaded”)

Move Zoom

Zoom follows the mouse or touch movement within the image container.

Basic Example

import { useZoomImageMove } from "@zoom-image/react"
import { useEffect, useRef } from "react"

function MoveZoomImage() {
  const containerRef = useRef<HTMLDivElement>(null)
  const { createZoomImage } = useZoomImageMove()

  useEffect(() => {
    if (containerRef.current) {
      createZoomImage(containerRef.current, {
        zoomImageSource: "/image-large.jpg",
      })
    }
  }, [])

  return (
    <div 
      ref={containerRef} 
      className="relative h-[300px] w-[200px] overflow-hidden cursor-crosshair"
    >
      <img className="h-full w-full" src="/image.jpg" alt="Move to zoom" />
    </div>
  )
}

State Properties

  • zoomedImgStatus: string - Loading status (“idle” | “loading” | “loaded”)

Click Zoom

Toggle between zoomed and normal states by clicking the image.

Basic Example

import { useZoomImageClick } from "@zoom-image/react"
import { useEffect, useRef } from "react"

function ClickZoomImage() {
  const containerRef = useRef<HTMLDivElement>(null)
  const { createZoomImage } = useZoomImageClick()

  useEffect(() => {
    if (containerRef.current) {
      createZoomImage(containerRef.current, {
        zoomImageSource: "/image-large.jpg",
      })
    }
  }, [])

  return (
    <div 
      ref={containerRef} 
      className="relative h-[300px] w-[200px] overflow-hidden cursor-crosshair"
    >
      <img className="h-full w-full" src="/image.jpg" alt="Click to zoom" />
    </div>
  )
}

State Properties

  • zoomedImgStatus: string - Loading status (“idle” | “loading” | “loaded”)

TypeScript Support

All hooks are fully typed. Import types from @zoom-image/core:
import type { 
  ZoomImageWheelState,
  ZoomImageHoverState,
  ZoomImageMoveState,
  ZoomImageClickState 
} from "@zoom-image/core"

Cleanup

All hooks automatically clean up on component unmount. The cleanup is handled internally using React’s useEffect cleanup function.

Live Examples

See the React adapter in action:

Build docs developers (and LLMs) love