DEV Community

Axit
Axit

Posted on • Originally published at aumiqx.com

Every Gesture Library on the Web is Wrong. Here's Why.

Every gesture library hooks into DOM events. Hammer.js (deprecated). use-gesture (React-only). interact.js (DOM-dependent).

But a gesture is just math.

A swipe is fast displacement along one axis. A tap is low drift over short time. A flick is high velocity over minimal distance. None of this requires a browser.

Introducing @aumiqx/gesture

Pure-math gesture recognition for JavaScript. ~6KB. Zero dependencies. Works in React, Node.js, Canvas, WebGL, Deno, Bun, or a server analyzing session replays.

import { recognize } from "@aumiqx/gesture"

const gesture = recognize([
  { x: 100, y: 200, t: 0 },
  { x: 300, y: 195, t: 32 },
  { x: 450, y: 201, t: 64 },
])

// {
//   type: "swipe",
//   direction: "right",
//   velocity: 5.47,
//   confidence: 0.92,
//   distance: 300,
//   curvature: 0.01,
//   predictedEnd: { x: 520, y: 203 }
// }
Enter fullscreen mode Exit fullscreen mode

Input coordinates. Get classification. That's it.

The Problem We Solved

Every existing gesture library is event-driven. They attach to the DOM, listen for pointer events, maintain internal state machines, and fire callbacks. This creates three fundamental limitations:

  1. DOM dependency — Can't use them on Canvas, WebGL, or server-side
  2. Framework lock-in — use-gesture is React-only, Hammer.js is vanilla-only
  3. No retroactive analysis — Can't classify gestures from logged data after the fact

Our library flips the model. A gesture is a mathematical pattern in a sequence of (x, y, timestamp) coordinates. The classification is pure computation:

  • Straight-line distance between first and last point
  • Path curvature — total path length divided by straight distance
  • Velocity — distance over time
  • Max drift from centroid — measures how stationary the touch was
  • Duration — total time elapsed

These five numbers determine every gesture type. No events needed.

What It Detects

Type Detection Logic Use Case
tap duration < 300ms, drift < 10px Button clicks, selection
long-press duration > 500ms, drift < 15px Context menus, drag mode
swipe distance > 30px, velocity > 0.3 px/ms Navigation, card dismissal
flick velocity > 1.5 px/ms, duration < 200ms List scrolling, page turning
pan slow movement, exceeds tap threshold Map dragging, object moving

Each result includes a confidence score (0-1), direction (up/down/left/right), and a predicted endpoint — where the gesture would land if it continued with friction decay.

Mid-Gesture Prediction

This is the feature that changes how you build UIs:

import { predict } from "@aumiqx/gesture"

// Call WHILE the user is still moving
const { likely, alternatives } = predict(partialPoints)

// likely.type = "swipe" (78% confidence)
// Start the transition NOW, before they finish
Enter fullscreen mode Exit fullscreen mode

Your UI reacts to gestures before they complete. The difference between "responsive" and "telepathic."

How It Compares

Feature Hammer.js use-gesture @aumiqx/gesture
DOM required Yes Yes No
Framework None React only Any / none
Server-side No No Yes
Canvas/WebGL No No Yes
Mid-gesture prediction No No Yes
Bundle size 7.3KB 12KB ~6KB
Maintained Deprecated Yes Yes
Dependencies 0 0 0

Real-World Use Cases

Canvas/WebGL Games — Gesture controls without DOM elements. Detect swipes, flicks, and holds directly from pointer data in your render loop.

Session Replay Analytics — Classify user gestures from logged pointer data on a server. Find rage-clicks, hesitant scrolls, and confused navigation patterns. Run in Node.js, not a browser.

Gesture Prediction — Call predict() mid-gesture to start UI responses before the gesture completes. Snappy interfaces that feel like they read your mind.

Accessibility — Classify shaky or imprecise input from users with motor impairments. Distinguish intentional gestures from tremor-induced movement by adjusting thresholds.

Custom Gesture Vocabularies — Combine recognized gestures into compound patterns. Swipe-then-hold = drag mode. Double-tap-then-swipe = selection gesture.

The Math Under the Hood

Every function is exported so you can build custom recognizers:

import {
  distance,            // Euclidean between two points
  straightLineDistance, // First to last point
  totalPathLength,     // Sum of all segments
  velocity,            // distance / time
  curvature,           // path / straight - 1 (0 = perfectly straight)
  maxDrift,            // max distance from centroid
  centroid,            // average position of all points
  angle,               // atan2 direction in radians
  predictEnd,          // extrapolate from velocity + friction
} from "@aumiqx/gesture"
Enter fullscreen mode Exit fullscreen mode

The entire library is trigonometry, linear regression, and threshold matching. No ML. No neural networks. No WASM. Just math.

Try It Live

We built an interactive demo with 12 gesture presets — tap, swipe (4 directions), flick, long-press, pan, circle, zigzag, diagonal, and unknown.

Click any preset to see the engine classify it step-by-step. Or draw your own gesture on the canvas and watch real-time prediction as you move.

Install

npm install @aumiqx/gesture
# or
pnpm add @aumiqx/gesture
Enter fullscreen mode Exit fullscreen mode

GitHub | npm | Live Demo

MIT licensed. TypeScript. Zero dependencies. ~6KB.


Built by Aumiqx — we build AI agents, workflow automations, and open-source tools that shouldn't work but do.

Top comments (0)