Skip to content
SiteEmail

This article covers three ways to handle touch in Gameface: native DOM touch events for simple cases, the Interaction Manager’s touchGestures module for named gesture patterns (tap, hold, drag, swipe, pinch, and rotate), and the touchEnabled flag that extends IM modules you already have wired for mouse. It also covers configuring the Gameface Player to simulate touch during development.

Gameface fires the touchstart, touchmove, touchend, and touchcancel events on DOM elements. You can attach them using the standard addEventListener method, and they work identically to mouse event listeners in a browser environment.

This is the most direct path for simple, self-contained interactions like a tap that toggles a panel or a touch that activates a button highlight. The following example shows how to wire a basic touch trigger to a button.

TouchButton.tsx
import Button from '@components/Basic/Button/Button';
const TouchButton = () => (
<Button id="touch-target" onTouchStart={() => console.log('Element touched')}>
Touch Me
</Button>
);

While raw events cover simple triggers, identifying gesture patterns from them means writing your own timing, distance, and multi-touch logic. The touchGestures module handles all of that for you.

The Gameface Player does not simulate touch events by default. To enable touch input during development, you must pass the --input touch flag when launching the Player.

Open your Player.bat file and append the flag to the existing command.

Player.bat
start "Player" /d "%wd%" "..\Player\Player.exe" --player "--url=coui://uiresources/Internal/DragAndDrop/drag-n-drop.html" --input touch

With this flag active, mouse clicks in the Player are forwarded as touch events.

The touchGestures module wraps raw touch sequences and resolves them into named gesture callbacks. You can import it directly from the Interaction Manager and call the method for the gesture you want to detect, passing in the target element and a callback

import { touchGestures } from "coherent-gameface-interaction-manager";
touchGestures.tap({
element: ".menu-item",
callback: openMenuItem,
});

Every gesture call returns an object with a .remove() method. You should save this return value whenever you need to clean up listeners on a screen unmount to prevent memory leaks.

cleanup-example.js
const tap = touchGestures.tap({
element: ".menu-item",
callback: openMenuItem,
});
// On screen unmount or component destruction:
tap.remove();

Tap detects a quick put-and-lift of one or more fingers. You can increase the tapsNumber property to detect double-taps or any specific multi-tap count.

double-tap.js
touchGestures.tap({
element: ".inventory-slot",
callback: function () {
openContextMenu();
},
tapsNumber: 2, // Required number of taps (default: 1)
tapTime: 200, // Max ms from down to up (default: 200)
betweenTapsTime: 500, // Max ms between consecutive taps (default: 500)
});

The hold gesture fires a single time after a finger has been down for a set duration without lifting.

hold.js
touchGestures.hold({
element: ".item",
callback: function () {
// Fires after holding for 1 second
showItemDetails();
},
time: 1000, // Duration in milliseconds (default: 1000)
});

The drag module tracks a single finger moving across the screen. It provides three callbacks:

  • onDragStart: covering the starting coordinates,
  • onDrag: live position on every move tick,
  • onDragEnd: the final position on lift.
drag.js
touchGestures.drag({
element: ".draggable-panel",
onDragStart: function (event) {
// event.x and event.y are the finger starting coordinates
panel.classList.add("is-dragging");
},
onDrag: function (position) {
// position.x and position.y update on every touchmove
panel.style.transform = `translate(${position.x}px, ${position.y}px)`;
},
onDragEnd: function () {
panel.classList.remove("is-dragging");
},
});

Swipe detects a fast movement followed by a lift. The callback receives a direction string, allowing one handler to cover multiple directions like ‘top’, ‘bottom’, ‘left’, or ‘right’.

swipe.js
touchGestures.swipe({
element: ".carousel",
callback: function (direction) {
// direction handles 8-way movement
if (direction === "left") carousel.next();
if (direction === "right") carousel.prev();
},
touchNumber: 1, // Fingers required for the swipe (default: 1)
});

Both pinch and rotate are two-finger gestures. Pinch tracks the distance change between fingers, while Rotate tracks their movement around a midpoint.

The pinch callback provides a pinchDelta (40 for stretching, -40 for pinching) and a midpoint coordinate.

pinch.js
touchGestures.pinch({
element: ".map",
callback: function ({ pinchDelta, midpoint }) {
// midpoint.x and midpoint.y are between the two fingers
adjustZoom(pinchDelta, midpoint);
},
});

The rotate callback provides an angle value between 0 and 360 degrees.

rotate.js
touchGestures.rotate({
element: ".compass",
callback: function (angle) {
compass.style.transform = `rotate(${angle}deg)`;
},
});

Interaction Manager modules that support mouse input (draggable, dropzone, resize, rotate, and zoom) also support touch interactions. This functionality is disabled by default and can be activated by flipping a single property.

touch-enabled.js
import { draggable, dropzone } from "coherent-gameface-interaction-manager";
const panel = new draggable({ element: ".panel" });
panel.touchEnabled = true; // The panel now responds to touch drags
const inventory = new dropzone({ element: ".item", dropzones: [".slot"] });
inventory.touchEnabled = true; // Items can be dragged into slots via touch

Setting touchEnabled = false removes the touch listeners without affecting the mouse path.