Rotation
useZoomPinch supports rotation via two-finger twist gestures and programmatic methods. Rotation is disabled by default — opt in via the gestures option.
Enable rotation
Section titled “Enable rotation”const { view, rotateTo, rotateBy } = useZoomPinch({ containerRef, gestures: { rotate: true },})Apply rotation in CSS
Section titled “Apply rotation in CSS”Add rotate() to your existing transform:
<div style={{ transform: `translate(${view.x}px, ${view.y}px) scale(${view.zoom}) rotate(${view.rotation ?? 0}deg)`, transformOrigin: "0 0", }}> {/* Your content */}</div>Gesture detection
Section titled “Gesture detection”When gestures.rotate is true, two-finger touch gestures detect both distance change (zoom) and angle change (rotation) simultaneously. The angle between touch points is tracked from touchstart through touchmove.
You can enable rotation alongside zoom (default) or independently:
// Both zoom and rotate during pinchuseZoomPinch({ containerRef, gestures: { rotate: true } })
// Rotate only — no zoom during pinchuseZoomPinch({ containerRef, gestures: { zoom: false, rotate: true } })Programmatic rotation
Section titled “Programmatic rotation”rotateTo(angle, options?)
Section titled “rotateTo(angle, options?)”Set rotation to an absolute angle in degrees:
rotateTo(0) // reset rotation instantlyrotateTo(90, { animate: true }) // rotate to 90° with animationrotateTo(-45, { animate: true, duration: 500 })rotateBy(delta, options?)
Section titled “rotateBy(delta, options?)”Rotate by a relative delta. Positive values rotate clockwise:
rotateBy(90, { animate: true }) // rotate 90° clockwiserotateBy(-45, { animate: true }) // rotate 45° counter-clockwiseRotation events
Section titled “Rotation events”Subscribe to rotation lifecycle:
useZoomPinch({ containerRef, gestures: { rotate: true }, onRotateStart: (view) => console.log("Rotation started", view.rotation), onRotateEnd: (view) => console.log("Rotation ended", view.rotation),})Reset includes rotation
Section titled “Reset includes rotation”resetView() resets rotation to 0 along with position and zoom:
// Resets to { x: 0, y: 0, zoom: 1, rotation: 0 }resetView({ animate: true })Example: rotation toolbar
Section titled “Example: rotation toolbar”function RotatableCanvas() { const containerRef = useRef<HTMLDivElement>(null) const { view, rotateBy, resetView } = useZoomPinch({ containerRef, gestures: { rotate: true }, })
return ( <div> <div style={{ display: "flex", gap: 8 }}> <button onClick={() => rotateBy(-90, { animate: true })}>↺ 90°</button> <button onClick={() => rotateBy(90, { animate: true })}>↻ 90°</button> <button onClick={() => resetView({ animate: true })}>Reset</button> <span>{Math.round(view.rotation ?? 0)}°</span> </div>
<div ref={containerRef} style={{ overflow: "hidden", touchAction: "none" }}> <div style={{ transform: `translate(${view.x}px, ${view.y}px) scale(${view.zoom}) rotate(${view.rotation ?? 0}deg)`, transformOrigin: "0 0", }} > {/* Your content */} </div> </div> </div> )}