Zero-GC multi-touch gesture recognition. Pan, pinch-to-zoom, velocity tracking.
Does NOT modify lite-pointer-tracker. Wraps it as a higher-order component.
| Feature | lite-gesture | Hammer.js | use-gesture | AlloyFinger |
|---|---|---|---|---|
| Zero-GC events | Yes (pre-allocated) | No | No | No |
| Velocity on release | Yes (measured) | Approximate | Yes | No |
| Pinch→Pan fallback | Yes (seamless) | Partial | Yes | No |
| AbortController cleanup | Yes | No | React only | No |
| PointerEvents native | Yes | Touch + Mouse | Yes | Touch only |
| Bundle size | < 2KB | ~7KB | ~5KB | ~3KB |
npm install @zakkster/lite-gestureimport { GestureTracker } from '@zakkster/lite-gesture';
const gesture = GestureTracker(canvas, {
onPanMove: (e) => {
ctx.translate(e.frameDx, e.frameDy);
},
onPanEnd: (e) => {
console.log('Release velocity:', e.vx, e.vy);
},
onPinchMove: (e) => {
currentZoom *= 1 + e.deltaScale;
},
});
// Later: gesture.destroy()let offsetX = 0, offsetY = 0, zoom = 1;
GestureTracker(canvas, {
onPanMove: (e) => { offsetX += e.frameDx; offsetY += e.frameDy; },
onPinchMove: (e) => { zoom *= 1 + e.deltaScale; },
});import { Spring } from '@zakkster/lite-ui';
const sx = new Spring(0);
GestureTracker(card, {
onPanMove: (e) => { sx.value = e.dx; card.style.transform = `translateX(${e.dx}px)`; },
onPanEnd: (e) => { sx.velocity = e.vx; sx.set(0); },
});let scale = 1, panX = 0, panY = 0;
GestureTracker(imageEl, {
onPinchMove: (e) => {
scale = e.scale;
panX = e.panX;
panY = e.panY;
imageEl.style.transform = `translate(${panX}px, ${panY}px) scale(${scale})`;
},
});| Callback | Event Fields |
|---|---|
onPanStart |
{ x, y } |
onPanMove |
{ x, y, dx, dy, frameDx, frameDy } |
onPanEnd |
{ x, y, dx, dy, vx, vy } — velocity in px/s |
onPinchStart |
{ centerX, centerY } |
onPinchMove |
{ scale, deltaScale, centerX, centerY, panX, panY } |
onPinchEnd |
(no fields) |
| Property | Description |
|---|---|
.isPanning |
Whether a pan gesture is active |
.isPinching |
Whether a pinch gesture is active |
.pointerCount |
Number of active touch points |
.destroy() |
Clean up all listeners |
MIT