pan

Pan gesture recognition for pointer interactions. Tracks drag movements with velocity, direction, and distance.

Terminal window
npm install --save @cereb/pan

Basic Usage

import { pan } from "@cereb/pan";
pan(element).on((signal) => {
const { phase, deltaX, deltaY } = signal.value;
if (phase === "move") {
element.style.transform = `translate(${deltaX}px, ${deltaY}px)`;
}
});

Signature

function pan(target: EventTarget, options?: PanOptions): Stream<PanSignal>

Options

OptionTypeDefaultDescription
thresholdnumber10Minimum movement (px) before gesture starts
direction"horizontal" | "vertical" | "all""all"Direction constraint for threshold

Direction Modes

// Only recognize horizontal pans
pan(element, { direction: "horizontal" })
// Only recognize vertical pans
pan(element, { direction: "vertical" })
// Recognize any direction (default)
pan(element, { direction: "all" })

Signal Value

The signal.value contains:

PropertyTypeDescription
phase"start" | "move" | "end" | "cancel"Current gesture phase
deltaXnumberX displacement from start (px)
deltaYnumberY displacement from start (px)
distancenumberTotal cumulative distance (px)
direction"up" | "down" | "left" | "right" | "none"Current movement direction
velocityXnumberX velocity (px/ms)
velocityYnumberY velocity (px/ms)
xnumberCurrent clientX
ynumberCurrent clientY
pageXnumberCurrent pageX
pageYnumberCurrent pageY

Phase Lifecycle

pointer down → (threshold met) → "start" → "move"* → "end" or "cancel"
  • start: Emitted once when threshold is met
  • move: Emitted repeatedly during drag
  • end: Pointer released normally
  • cancel: Gesture interrupted (e.g., system event)

Operators

axisLock

Locks the pan to the initially detected axis.

import { pan } from "@cereb/pan";
import { axisLock } from "@cereb/pan/operators";
pan(element)
.pipe(axisLock())
.on((signal) => {
// One of deltaX/deltaY will be 0 after axis is determined
element.style.transform = `translate(${signal.value.deltaX}px, ${signal.value.deltaY}px)`;
});
OptionTypeDefaultDescription
lockThresholdnumber0Movement needed to determine axis

Advanced: panRecognizer

Use as an operator with custom pointer sources:

import { singlePointer } from "cereb";
import { panRecognizer } from "@cereb/pan";
singlePointer(element)
.pipe(panRecognizer({ threshold: 10 }))
.on((signal) => { /* ... */ });