Zoom Controls
useSplitView exposes everything you need to build an imperative zoom toolbar: current state (view, displayZoomPct), setters (setView, centerZoom, resetView), and — through the re-exported useZoomPinch API — advanced helpers like zoomIn, zoomOut, and zoomTo.
The basics
Section titled “The basics”const { view, centerZoom, resetView, displayZoomPct } = useSplitView()
return ( <div> <button onClick={() => centerZoom(view.zoom * 1.5)}>Zoom In</button> <button onClick={() => centerZoom(view.zoom / 1.5)}>Zoom Out</button> <button onClick={() => resetView()}>Reset</button> <span>{displayZoomPct}%</span> </div>)centerZoom(targetZoom) zooms to the target level keeping the container center as the anchor, so the middle of what you see stays in place.
Display percentage vs raw zoom
Section titled “Display percentage vs raw zoom”There are two useful zoom values:
view.zoom— the raw zoom multiplier relative tofitScale.1means “content fits the container exactly.”displayZoomPct— a user-facing integer:round(view.zoom * fitScale * 100). This is what you typically show in the UI.
For a 3200×2000 image inside an 800×500 container, fitScale ≈ 0.25. When the user hasn’t zoomed, view.zoom = 1 but displayZoomPct = 25 — meaning “showing the image at 25% of its native size.”
<span>{displayZoomPct}%</span><button onClick={() => resetView()}>Reset</button>resetView() snaps the view back to { x: 0, y: 0, zoom: 1 }.
Snap to 100%
Section titled “Snap to 100%”If you want a button that shows content at its true native size (1 image pixel = 1 screen pixel), target 1 / fitScale:
const { fitScale, centerZoom } = useSplitView()
<button onClick={() => centerZoom(1 / fitScale)}>100%</button>Custom zoom steps
Section titled “Custom zoom steps”A discrete zoom ladder (25% / 50% / 100% / 200% / 400%):
const steps = [0.25, 0.5, 1, 2, 4]
<select value={Math.round(view.zoom * fitScale * 100) / 100} onChange={(e) => centerZoom(Number(e.target.value) / fitScale)}> {steps.map((s) => ( <option key={s} value={s}> {s * 100}% </option> ))}</select>Using zoomApi for advanced helpers
Section titled “Using zoomApi for advanced helpers”useSplitView exposes the advanced imperative helpers of its underlying useZoomPinch instance through zoomApi. They operate on the same container that drives the panes, so you get zoomIn, zoomOut, zoomTo, panTo, panBy, fitToRect, fitToContent, zoomToElement, screenToContent, and more without spinning up a separate instance:
const { view, zoomApi } = useSplitView()
<button onClick={() => zoomApi.zoomIn()}>Zoom in</button><button onClick={() => zoomApi.zoomOut()}>Zoom out</button><button onClick={() => zoomApi.panTo(100, 50, { animate: true, duration: 250 })}>Pan to detail</button><button onClick={() => zoomApi.fitToRect({ x: 0, y: 0, width: 400, height: 300 })}>Fit selection</button>centerZoom and resetView also accept AnimationOptions directly:
centerZoom(view.zoom * 2, { animate: true, duration: 250 })resetView({ animate: true })The re-exported easing functions (linear, easeOut, easeInOut) are available for custom AnimationOptions.easing.
Keyboard shortcuts
Section titled “Keyboard shortcuts”Add keyboard zoom by listening on the container:
const { containerRef, view, centerZoom, resetView } = useSplitView()
useEffect(() => { const el = containerRef.current if (!el) return const onKey = (e: KeyboardEvent) => { if (e.key === "+" || e.key === "=") centerZoom(view.zoom * 1.5) else if (e.key === "-") centerZoom(view.zoom / 1.5) else if (e.key === "0") resetView() } el.addEventListener("keydown", onKey) return () => el.removeEventListener("keydown", onKey)}, [view.zoom, centerZoom, resetView])
// And make the container focusable:<div ref={containerRef} tabIndex={0}>...</div>