Props
Static Props
Static properties are set during initialization and cannot be modified later.
container
- Type:
HTMLElement | SVGElement - Event listener container.
const observer = new Swipe({
container: document.getElementById('container'),
});
thumb
- Type:
HTMLElement | SVGElement | null - Default:
null - An element that triggers swipe start.
Movement is still calculated relative to the container —thumbonly defines where a user can grab. - See demo
const observer = new Swipe({
container: document.getElementById('container'),
thumb: document.getElementById('thumb'),
});
buttons
- Type:
number[] | ((type: TPointersType) => number[]) - Default:
[0] - Determines which mouse buttons trigger events.
- 0: Main button pressed, usually the left button or the un-initialized state
- 1: Auxiliary button pressed, usually the wheel button or the middle button (if present)
- 2: Secondary button pressed, usually the right button
- 3: Fourth button, typically the Browser Back button
- 4: Fifth button, typically the Browser Forward button
- See MouseEvent.button.
- See demo
Same shape as Pointers buttons.
const observer = new Swipe({
container: document.getElementById('container'),
buttons: [0], // left button click
buttons: [2], // right button click
buttons: [0, 2], // both buttons click
});
Different rules for mouse and touch:
const swipe = new Swipe({
container: document.getElementById('container'),
buttons: (type) => (type === 'touch' ? [0] : [2]),
});
pointers
-
Type:
number | ((type: TPointersType) => number) -
Default:
1 -
See demo
-
Required pointer count to activate swiping.
Useful for touch gestures such as two-finger pan.
If fewer pointers are present, swipe will not start.Same shape as
PointersminPointers.
Swipe sets bothminPointersandmaxPointerson its internalPointersinstance to this value.During move, Swipe tracks the center between active pointers (from
Pointers.move), not the first touch only.
const observer = new Swipe({
container: document.getElementById('container'),
pointers: 2, // swipe starts only with two fingers
});
One finger on mouse, two on touch:
const swipe = new Swipe({
container: document.getElementById('container'),
pointers: (type) => (type === 'mouse' ? 1 : 2),
});
Mutable Props
Mutable properties can be updated at runtime using .updateProps().
To apply different values by viewport or device, use Responsive with this component as the source. Props will update automatically when breakpoints change.
enabled
- Type:
boolean - Default:
true - Enables or disables swipe events.
const observer = new Swipe({
container: document.getElementById('container'),
enabled: false,
});
// change value
observer.updateProps({
enabled: true,
});
relative
- Type:
boolean - Default:
false - Calculates coordinates relative to the container rather than the page.
- See demo
const observer = new Swipe({
container: document.getElementById('container'),
relative: true,
});
// change value
observer.updateProps({
relative: false,
});
axis
- Type:
null | 'x' | 'y' - Default:
null - Primary swiping axis.
- See demo
const observer = new Swipe({
container: document.getElementById('container'),
axis: 'x',
});
// change value
observer.updateProps({
axis: 'y',
});
ratio
- Type:
number - Default:
1 - Scales movement on x, y, and angle after swipe starts.
Swipe activation still uses raw pointer distance, sothresholdis not affected byratio.
const observer = new Swipe({
container: document.getElementById('container'),
ratio: 1,
});
// change value
observer.updateProps({
ratio: 2,
});
grabCursor
- Type:
boolean - Default:
false - Shows "grab" and "grabbing" cursors on
thumb(if set) orcontainerduring interaction.
const observer = new Swipe({
container: document.getElementById('container'),
grabCursor: true,
});
// change value
observer.updateProps({
grabCursor: false,
});
willAbort
- Type:
(props: ISwipeCanMoveArg) => boolean - Default:
() => false - Runs before swipe starts and determines whether the gesture should be blocked.
Allows disabling swipe in specific UI states or when gesture conditions are not met.
const observer = new Swipe({
container: document.getElementById('container'),
willAbort: () => false,
});
// change value
observer.updateProps({
willAbort: ({ diff }) => diff.x > 5, // will prevent too fast swipe
});
threshold
- Type:
number - Default:
5 - Minimum swipe distance (px) to trigger swipe start.
const observer = new Swipe({
container: document.getElementById('container'),
threshold: 5,
});
// change value
observer.updateProps({
threshold: 3,
});
minTime
- Type:
number - Default:
0 - Minimum duration (ms) to trigger swipe move.
- Means that user click the container, waits some time, and only then swipe is available.
const observer = new Swipe({
container: document.getElementById('container'),
minTime: 0,
});
// change value
observer.updateProps({
minTime: 0,
});
directionThreshold
- Type:
number - Default:
50 - Minimum swipe distance (px) for directional callbacks.
- Swipe supports direction detection (toTop, toBottom, toLeft, toRight).
- To trigger a directional callback a user must swipe a certain amount of pixels -
directionThreshold.
const observer = new Swipe({
container: document.getElementById('container'),
directionThreshold: 50,
});
// change value
observer.updateProps({
directionThreshold: 10,
});
preventEdgeSwipe
- Type:
boolean - Default:
true - Prevents edge swiping (iOS swipe-back gesture).
const observer = new Swipe({
container: document.getElementById('container'),
preventEdgeSwipe: true,
});
// change value
observer.updateProps({
preventEdgeSwipe: false,
});
edgeSwipeThreshold
- Type:
number - Default:
20 - Edge swipe threshold (px) from the left/right edge.
const observer = new Swipe({
container: document.getElementById('container'),
edgeSwipeThreshold: 20,
});
// change value
observer.updateProps({
edgeSwipeThreshold: 25,
});
preventTouchMove
- Type:
boolean - Default:
true - Prevents
touchmovefrom scrolling the page while swiping.
Recommended to keep enabled for horizontal/vertical drags inside scrollable layouts.
const observer = new Swipe({
container: document.getElementById('container'),
preventTouchMove: true,
});
// change value
observer.updateProps({
preventTouchMove: false,
});
requireCtrlKey
- Type:
boolean - Default:
false - Requires Ctrl key for swipe (mouse only).
const observer = new Swipe({
container: document.getElementById('container'),
requireCtrlKey: true,
});
// change value
observer.updateProps({
requireCtrlKey: false,
});
bounceDuration
- Type:
number - Default:
250 - Duration (ms) of bounce-back when movement exceeds
bounds, release inertia does not run, andcanBounceallows it.
const swipe = new Swipe({
container: document.getElementById('container'),
bounds: () => ({ x: [0, 300] }),
bounceDuration: 250,
});
overflow
- Type:
() => number - Default:
() => 50 - Rubber-band distance past
bounds(px for x/y, degrees forangle). - See demo
const swipe = new Swipe({
container: document.getElementById('container'),
bounds: () => ({ y: [0, 500] }),
overflow: () => 80,
});
bounds
- Type:
null | ((coords: ISwipeCoords) => ISwipeAxes | null) - Default:
null - Movement limits per axis. Unset axis is unbounded. Values are normalized to
[min, max]. - The callback receives the full
ISwipeCoordssnapshot — usecoords.scale,coords.movement, etc. when limits depend on zoom or layout. - Limits are re-read on every move update (including after
setScale). - Use
movementandscalein callbacks for transforms. - See demo
const swipe = new Swipe({
container: document.getElementById('wrapper'),
thumb: document.getElementById('thumb'),
relative: true,
bounds: ({ scale }) => ({
x: [0, wrapper.clientWidth - thumb.clientWidth * scale],
y: [0, wrapper.clientHeight - thumb.clientHeight * scale],
}),
onMove: ({ movement, scale }) => {
thumb.style.transform = `translate(${movement.x}px, ${movement.y}px) scale(${scale})`;
},
});
Static limits (callback may ignore coords):
const swipe = new Swipe({
container: document.getElementById('wrapper'),
relative: true,
bounds: () => ({ x: [0, 300], y: [0, 300] }),
onMove: ({ movement }) => {
thumb.style.transform = `translate(${movement.x}px, ${movement.y}px)`;
},
});
recalculateBoundsOnInertia
- Type:
boolean - Default:
true - When
true,boundsare re-read on every move update while release inertia is active.
Set tofalsewhen bounds are static during inertia (for example inSnap) to avoid extra layout work.
const swipe = new Swipe({
container: document.getElementById('container'),
inertia: true,
bounds: () => ({ x: [0, 300] }),
recalculateBoundsOnInertia: false,
});
snap
- Type:
null | (() => ISwipeAxes | null) - Default:
null - Snap targets per axis in movement space.
const swipe = new Swipe({
container: document.getElementById('container'),
relative: true,
snap: () => ({ angle: [0, 90, 180] }),
snapRadius: 15,
});
canBounce
- Type:
() => boolean - Default:
() => true - When it returns
false, overflow bounce-back on release is skipped (inertia may still run).
const swipe = new Swipe({
container: document.getElementById('container'),
bounds: () => ({ x: [0, 300] }),
canBounce: () => false,
});
// change value
swipe.updateProps({
canBounce: () => true,
});
snapRadius
- Type:
number | null - Default:
null - Max distance to a snap target (same units as the axis). Falsy = no radius limit.
const swipe = new Swipe({
snap: () => ({ angle: [0, 90, 180] }),
snapRadius: 10,
});
inertia
- Type:
boolean - Default:
false - Enables RAF-based release inertia after swipe end.
- See demo
const swipe = new Swipe({
container: document.getElementById('container'),
inertia: true,
});
inertiaDecay
- Type:
number - Default:
0.05 - Velocity decay per frame during inertia (higher = stops sooner).
- See demo
const swipe = new Swipe({
inertia: true,
inertiaDecay: 0.05,
});
inertiaBounceEase
- Type:
number - Default:
0.3 - Easing factor for pulling inertia back inside
bounds(per frame, FPS-independent). - See demo
const swipe = new Swipe({
inertia: true,
bounds: () => ({ x: [0, 400] }),
inertiaBounceEase: 0.3,
});
inertiaRatio
- Type:
number - Default:
1 - Extra multiplier for release velocity. Effective scale is
ratio× inertiaRatio. - See demo
const swipe = new Swipe({
inertia: true,
inertiaRatio: 1.5,
});
inertiaDistanceModifier
- Type:
null | ((distance: ISwipeVec3) => ISwipeVec3 | null) - Default:
null - Called once before release inertia starts with predicted inertia distance (
x/yin px,anglein degrees).
Return a vector to override the total inertia travel, ornullto keep the default decay-based inertia. - See demo
const swipe = new Swipe({
inertia: true,
inertiaDistanceModifier: (distance) => ({
x: clamp(distance.x, -100, 100),
y: distance.y,
angle: 0,
}),
});
inertiaThreshold
- Type:
number - Default:
1 - Minimum release speed to start inertia (px/s for x/y, deg/s for
angle).
TriggersinertiaFailwhen both linear and angular speed are below this value.
const swipe = new Swipe({
inertia: true,
inertiaThreshold: 1,
});
maxVelocity
- Type:
ISwipeVec3 - Default:
{ x: 7, y: 7, angle: 3 } - Max release velocity per axis (coord/ms for x/y, deg/ms for
angle).
Falsy axis value disables inertia on that axis.
const swipe = new Swipe({
inertia: true,
maxVelocity: { x: 10, y: 10, angle: 5 },
});
Deprecated inertia props
Timelined inertia (inertiaDuration, inertiaEasing) and velocityModifier are no longer applied. Use RAF inertia props above (inertiaDecay, inertiaBounceEase, inertiaThreshold, maxVelocity).