What if gestures were just math?
Every gesture library listens to the DOM. This one reads a list of (x, y, t) points and tells you what the hand did: tap, swipe, flick, hold or pan. It runs anywhere those points exist.
- size
- ~6KB
- size
- dependencies
- 0
- dependencies
- gesture types
- 7
- gesture types
01 · Try it
Draw something. Watch it think.
Draw anything here.
swipe · tap · hold · flick · wander · or pick a preset
Confidence race
waiting
- tap0%
- long-press0%
- swipe0%
- flick0%
- pan0%
The working
Every number the classifier looks at lands here: distance, duration, velocity, curvature and drift.
02 · The API
Three functions. That's the whole API.
01 · When the finger lifts
recognize(points)Classifies a finished gesture and returns its type, direction, confidence, velocity and more.
const g = recognize(points);
// { type: "swipe", direction: "right",
// confidence: 0.92, velocity: 0.78, ... }02 · While it's still moving
predict(points)Classifies a partial trace, so the UI can start responding before the gesture ends. The race above runs on it.
const { likely, alternatives } = predict(points);
// likely: { type: "swipe", confidence: 0.7 }
// alternatives: [{ type: "pan", ... }]03 · Two taps, one intent
recognizeDoubleTap(a, b)Checks two tap sequences for timing and distance and returns a double-tap, or null.
const dbl = recognizeDoubleTap(first, second);
// { type: "double-tap", interval: 180,
// confidence: 0.95, center: { x, y } }03 · Where it goes
Anywhere there are coordinates. Not just the browser.
Canvas and WebGL
Gesture controls with no DOM elements. Read swipes, flicks and holds straight from pointer data in your render loop.
Session replays
Classify logged pointer data on a server to find rage taps, hesitant drags and confused navigation.
Predictive UI
Call predict() mid-gesture and start the response before the finger lifts.
Accessibility
Tune thresholds for shaky or imprecise input, so intent isn't mistaken for tremor.
Gesture vocabularies
Chain results into compound moves: swipe then hold for drag mode, double-tap then swipe to select.
Any input source
Mouse, touch, pen or trackpad. If it produces (x, y, t), it works on web, mobile and desktop.
04 · Under the hood
Ten small functions. No model, no training data.
| Function | Formula | What it measures |
|---|---|---|
| distance(a, b) | √((bx−ax)² + (by−ay)²) | Distance between two points |
| straightLineDistance(pts) | distance(first, last) | First point to last |
| totalPathLength(pts) | Σ d(i, i+1) | Every segment added up |
| duration(pts) | last.t − first.t | Time from first to last point |
| velocity(pts) | straightDist / duration | Average speed |
| curvature(pts) | pathLen / straightDist − 1 | How far the path bends from straight |
| maxDrift(pts) | max d(p, centroid) | Furthest any point strays from the middle |
| centroid(pts) | avg(x), avg(y) | Average position |
| angle(a, b) | atan2(by−ay, bx−ax) | Direction between two points |
| predictEnd(pts) | velocity × friction decay | Where the motion is heading a few frames on |
- DOM required
- No
- Runtime
- Browser, Node, Deno, Bun
- Framework
- Any, or none
- Types
- TypeScript included
- Models or training
- None. Thresholds only
- Thresholds
- All configurable