UNPKG

js-draw

Version:

Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.

75 lines (74 loc) 3.17 kB
import { InputEvtType, isPointerEvt } from '../../inputEvents.mjs'; import InputMapper from './InputMapper.mjs'; import StationaryPenDetector, { defaultStationaryDetectionConfig, } from '../util/StationaryPenDetector.mjs'; import { PointerDevice } from '../../Pointer.mjs'; export default class ContextMenuRecognizer extends InputMapper { constructor() { super(); this.canShowContextMenu = false; this.stationaryDetector = null; this.clickTolerance = 12; } /** * In general, only certain events (i.e. touchscreens) are expected to be able to * create long-press menus. This method checks whether `event` was generated by * one such device. */ canMakeLongPressMenuEvent(event) { const allowedDevices = [PointerDevice.Touch]; return event.allPointers.length === 1 && allowedDevices.includes(event.current.device); } onEvent(event) { const sendContextMenuEvent = () => { if (!isPointerEvt(event)) return false; if (this.canShowContextMenu) { const eventHandled = this.emit({ kind: InputEvtType.ContextMenu, screenPos: event.current.screenPos, canvasPos: event.current.canvasPos, }); if (eventHandled) { this.emit({ kind: InputEvtType.GestureCancelEvt, }); return true; } } return false; }; if (event.kind === InputEvtType.PointerDownEvt) { if (event.allPointers.length === 1) { this.canShowContextMenu = true; this.contextMenuTriggerPointer = event.current; this.contextMenuStartPoint = event.current.screenPos; if (this.canMakeLongPressMenuEvent(event)) { this.stationaryDetector = new StationaryPenDetector(event.current, defaultStationaryDetectionConfig, sendContextMenuEvent); } } else { this.canShowContextMenu = false; } } else if (event.kind === InputEvtType.PointerMoveEvt) { if (this.canShowContextMenu) { this.stationaryDetector?.onPointerMove(event.current); // Only clicks/stationary long presses can create context menu events. const deltaPosition = event.current.screenPos.minus(this.contextMenuStartPoint); const threshold = this.clickTolerance; if (deltaPosition.length() > threshold) { this.canShowContextMenu = false; } } } else if (event.kind === InputEvtType.PointerUpEvt) { this.stationaryDetector?.destroy(); if (this.contextMenuTriggerPointer?.id === event.current.id && this.contextMenuTriggerPointer.device === PointerDevice.RightButtonMouse && sendContextMenuEvent()) { return true; } } return this.emit(event); } }