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

Installation

npm install @zoom-image/solid

Available Primitives

The Solid adapter exports four primitives, 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

Primitive Return Values

Each primitive returns an object with:
  • createZoomImage - Function to initialize zoom on a container element
  • zoomImageState - Reactive state store (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/solid"
import { onMount } from "solid-js"
import type { Component } from "solid-js"

const WheelZoomImage: Component = () => {
  let containerRef: HTMLDivElement
  const { createZoomImage, zoomImageState } = useZoomImageWheel()

  onMount(() => {
    createZoomImage(containerRef)
  })

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

export default WheelZoomImage

Complete Example with Controls

import { useZoomImageWheel } from "@zoom-image/solid"
import { cropImage } from "@zoom-image/core"
import { onMount, createSignal } from "solid-js"
import type { Component } from "solid-js"

const AdvancedWheelZoom: Component = () => {
  let containerRef: HTMLDivElement
  const [croppedImage, setCroppedImage] = createSignal<string>("")
  
  const {
    createZoomImage,
    zoomImageState,
    setZoomImageState,
  } = useZoomImageWheel()

  onMount(() => {
    createZoomImage(containerRef)
  })

  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.querySelector('img') as HTMLImageElement,
      positionX: zoomImageState.currentPositionX,
      positionY: zoomImageState.currentPositionY,
      rotation: zoomImageState.currentRotation,
    })
    setCroppedImage(result)
  }

  return (
    <div>
      <div class="flex gap-4">
        <div ref={containerRef} class="h-[300px] w-[200px]">
          <img class="h-full w-full" src="/image.jpg" alt="Zoomable" />
        </div>
        {croppedImage() && (
          <img src={croppedImage()} alt="Cropped" class="h-[300px] w-[200px]" />
        )}
      </div>
      
      <div class="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>
  )
}

export default AdvancedWheelZoom

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/solid"
import { onMount } from "solid-js"
import type { Component } from "solid-js"

const HoverZoomImage: Component = () => {
  let containerRef: HTMLDivElement
  let zoomTargetRef: HTMLDivElement
  const { createZoomImage } = useZoomImageHover()

  onMount(() => {
    createZoomImage(containerRef, {
      zoomImageSource: "/image-large.jpg",
      customZoom: { width: 300, height: 500 },
      zoomTarget: zoomTargetRef,
      scale: 2,
    })
  })

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

export default HoverZoomImage

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/solid"
import { onMount } from "solid-js"
import type { Component } from "solid-js"

const MoveZoomImage: Component = () => {
  let containerRef: HTMLDivElement
  const { createZoomImage } = useZoomImageMove()

  onMount(() => {
    createZoomImage(containerRef, {
      zoomImageSource: "/image-large.jpg",
    })
  })

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

export default MoveZoomImage

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/solid"
import { onMount } from "solid-js"
import type { Component } from "solid-js"

const ClickZoomImage: Component = () => {
  let containerRef: HTMLDivElement
  const { createZoomImage } = useZoomImageClick()

  onMount(() => {
    createZoomImage(containerRef, {
      zoomImageSource: "/image-large.jpg",
    })
  })

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

export default ClickZoomImage

State Properties

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

TypeScript Support

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

Reactive Stores

The zoomImageState returned by each primitive is a reactive store created with Solid’s createStore. You can access properties directly in your JSX and Solid will automatically track dependencies:
const { zoomImageState } = useZoomImageWheel()

// Solid automatically tracks access to zoomImageState.currentZoom
return <p>Zoom: {zoomImageState.currentZoom}</p>
You can also use effects to react to state changes:
import { createEffect } from "solid-js"

const { zoomImageState } = useZoomImageWheel()

createEffect(() => {
  console.log('Zoom changed:', zoomImageState.currentZoom)
})

Cleanup

All primitives automatically clean up on component unmount using Solid’s onCleanup lifecycle function.

Live Examples

See the Solid adapter in action:

Build docs developers (and LLMs) love