Touchpad
Touchpad tracks up to ten simultaneous touches with per-touch position and frame transitions. It is intended for touch-screen events. Laptop trackpads normally appear through Mouse.
Input connects and updates one automatically, or the device can be used on its own.
import {
TouchIdentifier,
Touchpad
} from "@jolly-pixel/controls";
const canvas = document.querySelector("canvas");
if (!canvas) {
throw new Error("No canvas element found");
}
const touchpad = new Touchpad({ canvas });
touchpad.connect();
function gameLoop() {
touchpad.update();
if (touchpad.wasStarted(TouchIdentifier.primary)) {
console.log("Primary touch started");
}
if (touchpad.isTwoFingerGesture) {
console.log("Two touches are down");
}
requestAnimationFrame(gameLoop);
}
gameLoop();Constructor
interface TouchpadOptions {
canvas: CanvasAdapter;
}
new Touchpad(options: TouchpadOptions)An HTMLCanvasElement satisfies the structural CanvasAdapter type. The adapter type is not exported from the package root.
Types
const TouchIdentifier = {
primary: 0,
secondary: 1,
tertiary: 2
} as const;
type TouchAction = number | keyof typeof TouchIdentifier;
type TouchPosition = { x: number; y: number };
interface TouchState {
isDown: boolean;
wasStarted: boolean;
wasEnded: boolean;
position: TouchPosition;
}Each touch takes the lowest free slot when it starts and keeps it until it ends, whatever its browser identifier. TouchIdentifier names slots 0, 1, and 2; numeric actions address slots 0 through 9. Touches beyond the tenth are ignored.
State and gestures
declare class Touchpad {
static readonly MaxTouches: 10;
readonly wasActive: boolean;
readonly isOneFingerGesture: boolean;
readonly isTwoFingerGesture: boolean;
readonly isThreeFingerGesture: boolean;
update(): void;
sample(): void;
publish(reader: InputReader): void;
reset(): void;
}isDown() changes as soon as touch events arrive. update() publishes wasStarted and wasEnded for one input step. A touch that starts and ends between two updates reports both.
update() is sample() then publish("step"). A fixed-step engine calls sample() and publish(reader) separately; see Input.
The gesture getters report whether slots 0, 0 + 1, or 0 + 1 + 2 are currently down.
wasActive is true when the latest sample had a touch down or an edge. reset() frees every slot and drops pending edges without reporting an end.
Queries
interface Touchpad {
touchState(identifier: TouchAction): TouchState;
isDown(identifier: TouchAction): boolean;
wasStarted(identifier: TouchAction): boolean;
wasEnded(identifier: TouchAction): boolean;
}touchState() returns a new snapshot of one slot.
A slot below 0 or at least Touchpad.MaxTouches throws an error whose message contains the invalid index. A named action resolves through TouchIdentifier.
Position
interface Touchpad {
viewportPosition(
identifier: TouchAction
): Vector2Like;
viewportPositionTo<T extends Vector2Like>(
identifier: TouchAction,
out: T
): T;
}Touch positions use canvas-local CSS pixels. Start and move handlers subtract the target's bounding rectangle from clientX and clientY.
viewportPosition() normalizes the stored position into [-1, 1] on both axes and flips Y. It returns a new object. viewportPositionTo() writes into a caller-owned object and returns it.
Vector2Like is the structural { x: number; y: number } shape used by the output method. It is exported from the package root.
Events
type TouchEvents = {
start: (
touch: Touch,
position: TouchPosition
) => void;
move: (
touch: Touch,
position: TouchPosition
) => void;
end: (touch: Touch) => void;
};start and move receive the live position object of the touch's slot. Later movement mutates that object, so copy it if the listener needs a snapshot. end receives only the browser Touch.
Touch start, move, end, and cancel handlers call preventDefault(). A cancel updates down state and emits end.
Availability
static isAvailable(): booleanReturns whether document.documentElement has an ontouchstart property. The method reads the global document and therefore requires a DOM-like environment.
Lifecycle
connect(): void
disconnect(): voidconnect() registers touchstart, touchend, touchmove, and touchcancel listeners on the canvas. disconnect() removes them without resetting state.