pan

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

Basic Usage

import { pan } from "cereb";
pan(element).on((signal) => {
const { phase, delta } = signal.value;
const [dx, dy] = delta;
if (phase === "move") {
element.style.transform = `translate(${dx}px, ${dy}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
cursor[number, number]Current position [x, y] (client)
pageCursor[number, number]Current position [pageX, pageY] (page)
delta[number, number]Displacement from start [deltaX, deltaY]
velocity[number, number]Velocity [vx, vy] (px/ms)
distancenumberTotal cumulative distance (px)
direction"up" | "down" | "left" | "right" | "none"Current movement direction

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)

With axisLock Operator

Locks the pan to the initially detected axis.

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