pa_gesture
v1.4.0
Published
Composable gesture controller for drag, pan, rotate, zoom, and CSS variable output.
Maintainers
Readme
pa_gesture
Composable gesture control for DOM elements.
- One entry point:
gesture(target, ...features) - Feature-based setup:
drag(),pan(),zoom(),cssVars() - Continuous values via
getState() - Discrete actions via
on("click"),on("doubleClick"),on("dragStart")
Install
npm install pa_gestureQuick Start
import gesture, {
drag,
doubleClick,
pan,
rotate,
zoom,
cssVars,
} from "pa_gesture";
const ctrl = gesture(
"#knob",
drag(),
doubleClick(),
pan({ damping: 0.2 }),
rotate({ damping: 0.2 }),
zoom({ min: 0.5, max: 4, damping: 0.2 }),
cssVars()
);
ctrl.on("doubleClick", ctrl.reset);#knob {
transform: translate(-50%, -50%);
}cssVars() appends gesture transforms after the existing computed transform. It does not overwrite your base layout transform.
State
const state = ctrl.getState();{
x,
y,
zoom,
angle,
dragging,
pinching,
isPressed,
lastClickAt,
pointerX,
pointerY
}angleis in radians.isPressedistruewhile a mouse button or touch pointer is down.lastClickAtis the timestamp of the last confirmedclick.
This is useful for render loops and shaders:
const state = ctrl.getState();
uniforms.uPressed.value = Number(state.isPressed);
uniforms.uLastClickAt.value = state.lastClickAt;
uniforms.uZoom.value = state.zoom;
uniforms.uAngle.value = state.angle;Events
const off = ctrl.on("click", (event) => {
console.log(event.type, event.target, event.state);
});
off();Supported event types:
clickdoubleClickdragStartdragMovedragEnd
Payload shape:
{
type,
target,
controller,
state,
x,
y,
originalEvent,
dx,
dy,
totalX,
totalY
}Targets
Accepted target types:
HTMLElement- CSS selector string
NodeListHTMLElement[]
Return rules:
gesture(target, ...)Returns aControllerfor one match, aControllerGroupfor multiple matches, and throws for zero matches.gesture.one(target, ...)Requires exactly one match.gesture.all(target, ...)Requires at least one match and always returns aControllerGroup.
Controller
ctrl.getState()
ctrl.setState(patch, options?)
ctrl.reset(next?, options?)
ctrl.on(type, handler)
ctrl.off(type, handler)
ctrl.destroy()Examples:
ctrl.setState({ x: 120, y: 40, zoom: 1.5, angle: 0.5 });
ctrl.setState({ x: 0, y: 0 }, { immediate: false });
ctrl.reset();
ctrl.reset({}, { damping: 0.08 });reset() resets only that controller.
ControllerGroup
const group = gesture.all(".card", click(), doubleClick(), drag(), pan(), cssVars());group.get(0)
group.get(element)
group.getState()
group.getState(0)
group.setState(patch, options?)
group.reset(targetOrIndexOrEvent, next?, options?)
group.resetAll(next?, options?)
group.forEach((ctrl, el, index) => {})
group.on(type, handler)
group.off(type, handler)
group.destroy()Examples:
group.on("doubleClick", group.reset);
group.reset(0);
group.reset(someElement);
group.resetAll();group.reset(...)resets one target.group.resetAll(...)resets every target.
Features
drag({
button: 0,
threshold: 4,
})
click({
button: 0,
maxDistance: 6,
maxDelay: 250,
})
doubleClick({
button: 0,
delay: 250,
maxDistance: 6,
})
pan({
axis: "both",
damping: 0.2,
})
rotate({
damping: 0.2,
})
zoom({
min: 0.1,
max: 10,
damping: 0.2,
wheel: true,
pinch: true,
})
cssVars({
x: "--x",
y: "--y",
zoom: "--zoom",
angle: "--angle",
transform: "auto",
cursor: "auto",
touchAction: "auto",
draggingAttr: true,
})Notes:
drag()detects drag. It does not move the element by itself.pan()writes drag delta intoxandy.rotate()writes pointer motion intoangle.zoom()handles wheel and pinch zoom.cssVars()writes CSS custom properties and can manage transform, cursor, touch-action, anddata-pa-dragging.
CSS Variables
By default, cssVars() writes:
--x--y--zoom--angle
With cssVars(), a single element can be styled like this:
.card {
transform:
translate(var(--x), var(--y))
rotate(var(--angle))
scale(var(--zoom));
}Build
npm run build