Gestures Overview
React UI Animate has two layers for handling pointer/touch/wheel input:
Gesture+useGesture: the low-level primitive.Gesture.Pan(),.Move(),.Wheel(),.Scroll(),.Swipe(),.Hover(),.Pinch(), and.Rotate()are chainable builders that describe a gesture;useGestureattaches the built descriptor to a ref, an array of refs, orwindow. Every gesture type is registered against the same shared per-element tracker, so multipleuseGesturecalls on one node compose instead of fighting each other.useDrag: a high-level convenience hook built on top ofGesture.Pan(). It returns ready-to-usex/yAnimateValues with momentum, bounds, and rubber-banding built in, so you don't have to wirewithDecay/withSpringyourself for the common drag-a-thing case.
Reach for useDrag first for draggable elements. Reach for Gesture +
useGesture for anything else: scroll tracking, wheel/zoom controls, swipe
detection, hover/cursor effects, or pinch-to-zoom and rotate.
tip
Start with useDrag for the common case. Drop down to useGesture when you need a gesture type that isn't drag.
Available gesture types
| Builder | Fires | Use it for |
|---|---|---|
Gesture.Pan() | onStart / onChange / onEnd / onFinalize | Custom drag logic (useDrag covers most of this already) |
Gesture.Move() | onStart / onChange / onEnd | Cursor-follow effects, hover-position tracking |
Gesture.Wheel() | onStart / onChange / onEnd | Trackpad/wheel-driven zoom or custom scroll |
Gesture.Scroll() | onStart / onChange / onEnd | Scroll-linked animation, parallax, progress bars |
Gesture.Swipe() | onSwipe (once, on release) | Flick-to-dismiss, carousels, swipe navigation |
Gesture.Hover() | onStart / onChange / onEnd | Hover-in/out state |
Gesture.Pinch() | onStart / onChange / onEnd / onFinalize | Two-finger zoom |
Gesture.Rotate() | onStart / onChange / onEnd / onFinalize | Two-finger rotation |
See useGesture for the full API and one example per builder, and useDrag for the drag convenience hook.
Common pattern: drag with a spring back
import { useRef } from 'react';
import { useDrag, animate } from 'react-ui-animate';
function DraggableCard() {
const ref = useRef(null);
const { x, y } = useDrag(ref);
return (
<animate.div
ref={ref}
style={{ translateX: x, translateY: y, cursor: 'grab' }}
>
Drag me
</animate.div>
);
}
useDrag springs back to bounds automatically when bounds is set, and
flings with momentum on release by default. See useDrag for
every option.
Best practices
Do
- Animate
translateX/translateY(GPU-accelerated transforms), notleft/top. - Let
useDrag'smomentum/elastic/boundsoptions do the physics work instead of hand-rollingwithDecayfor simple drag cases. - Pass a stable
ref. Gesture registration happens once on mount and stays live for config/handler changes, but the element itself isn't expected to swap out from under it.
Don't
- Don't skip a fallback/keyboard interaction for anything gesture-driven. Gestures should enhance an already-usable UI, not be the only way to trigger an action.
- Don't set overly small
minDistance/thresholdvalues. A little slop avoids gestures firing on what was meant to be a click/tap.