Plugin: Touch Zones
TouchZonesPlugin (id 'touch-zones') renders a transparent tap-zone overlay for touch and mobile input, single-tap to show/hide controls or toggle playback, double-tap to seek or adjust volume, the interaction model most streaming apps train users to expect. It sits at a z-index between the video element and the desktop UI controls overlay, so it intercepts taps meant for the video area without blocking button clicks on a control bar mounted above it.
Options
| Option | Type | Default | Purpose |
|---|---|---|---|
doubleTapThreshold | number | 300 | Milliseconds between taps that still counts as a double-tap. |
seekSeconds | number | 10 | Seconds to seek on a double-tap in the left/right zones. |
disableClickToPause | boolean | false | Stop the center zone’s single-tap from toggling playback. Mirrors DesktopUiPlugin’s own disableClickToPause, both plugins ship independent click handlers on different DOM layers, so the same override is needed on both when a consumer wants a custom center-tap behavior. |
Zone layout
A 3-column x 6-row grid. Desktop/tablet touch gets three columns spanning the full height (seek-back, playback+fullscreen, seek-forward); mobile additionally splits two rows off the top and bottom of the center column for volume up/down, detected via ontouchstart presence or navigator.maxTouchPoints.
| Zone | Single-tap | Double-tap |
|---|---|---|
| Left (seek back) | Dismiss controls if visible, no-op otherwise, touchstart already woke them. | Seek back seekSeconds. |
| Center (playback) | Toggle playback (unless disableClickToPause). | Toggle fullscreen. |
| Right (seek forward) | Dismiss controls if visible, no-op otherwise, touchstart already woke them. | Seek forward seekSeconds. |
| Top / bottom of center, mobile only | Dismiss controls if visible, no-op otherwise, touchstart already woke them. | Volume up / down. |
Each seek zone shows a floating circular indicator (chevron icon plus accumulated seconds, e.g. “-30s” after three rapid taps) that lazily mounts on first use and collapses back to zero after roughly a second of no further taps in that direction.
Rules & restrictions
- Single-tap “toggle controls” reads a snapshot of visibility captured at
pointerdownin the capture phase, beforeDesktopUiPlugin’s own bubble-phase wake handler can mutate the DOM. Without this, a tap from a hidden state would show controls ontouchstartand then immediately hide them again when the deferred single-tap handler read the just-added.activeclass, a show-then-hide flicker that makes the tap look like it did nothing. - Mobile detection is a one-shot capability check at plugin startup (
ontouchstartpresence ormaxTouchPoints > 0), not a live pointer-type check, a touch-capable laptop used with a mouse still gets the mobile volume zones. - Emits
player.emit('activity', { active })to coordinate withDesktopUiPlugin’s auto-hide timer, this plugin has no visible chrome of its own to hide.
How to extend it
There’s no subclass hook for zone geometry, the grid positions are internal. A different zone layout (a 5-zone grid, a corner-only seek gesture) is a new plugin built against the same player methods (rewind, forward, togglePlayback, toggleFullscreen, volumeUp, volumeDown) rather than a subclass:
import nmplayer from '@nomercy-entertainment/nomercy-video-player';
import { TouchZonesPlugin } from '@nomercy-entertainment/nomercy-video-player/plugins/touch-zones';
const player = nmplayer('player');
player.addPlugin(TouchZonesPlugin, {
seekSeconds: 15,
doubleTapThreshold: 250,
});
Next steps
- Plugin: Desktop UI: the control bar this plugin’s
activityevents show and hide.