This repository has been archived on 2022-03-12. You can view files and clone it, but cannot push or open issues or pull requests.
2021-04-02 02:24:13 +03:00

151 lines
3.8 KiB
JavaScript

import Hammer from '@egjs/hammerjs';
import State from '../State';
import {
CONTENT_TOUCHES_DELAY,
CONTENT_TOUCHES_QUICK_TAP_END_DELAY,
} from './constants';
import DiscreteGestureHandler from './DiscreteGestureHandler';
import { fireAfterInterval, isValidNumber, isnan } from './utils';
class PressGestureHandler extends DiscreteGestureHandler {
get name() {
return 'press';
}
get minDurationMs() {
return isnan(this.config.minDurationMs) ? 5 : this.config.minDurationMs;
}
get maxDist() {
return isnan(this.config.maxDist) ? 9 : this.config.maxDist;
}
get NativeGestureClass() {
return Hammer.Press;
}
shouldDelayTouches = true;
simulateCancelEvent(inputData) {
// Long press never starts so we can't rely on the running event boolean.
this.hasGestureFailed = true;
this.cancelEvent(inputData);
}
updateHasCustomActivationCriteria({ shouldCancelWhenOutside, maxDistSq }) {
return shouldCancelWhenOutside || !isValidNumber(maxDistSq);
}
getState(type) {
return {
[Hammer.INPUT_START]: State.BEGAN,
[Hammer.INPUT_MOVE]: State.ACTIVE,
[Hammer.INPUT_END]: State.END,
[Hammer.INPUT_CANCEL]: State.CANCELLED,
}[type];
}
getConfig() {
if (!this._hasCustomActivationCriteria) {
// Default config
// If no params have been defined then this config should emulate the native gesture as closely as possible.
return {
shouldCancelWhenOutside: true,
maxDistSq: 10,
};
}
return this.config;
}
getHammerConfig() {
return {
...super.getHammerConfig(),
// threshold: this.maxDist,
time: this.minDurationMs,
};
}
onGestureActivated(ev) {
this.onGestureStart(ev);
}
shouldDelayTouchForEvent({ pointerType }) {
// Don't disable event for mouse input
return this.shouldDelayTouches && pointerType === 'touch';
}
onGestureStart(ev) {
this.isGestureRunning = true;
clearTimeout(this.visualFeedbackTimer);
this.initialEvent = ev;
this.visualFeedbackTimer = fireAfterInterval(() => {
this.sendGestureStartedEvent(this.initialEvent);
this.initialEvent = null;
}, this.shouldDelayTouchForEvent(ev) && CONTENT_TOUCHES_DELAY);
}
sendGestureStartedEvent(ev) {
clearTimeout(this.visualFeedbackTimer);
this.visualFeedbackTimer = null;
this.sendEvent({
...ev,
eventType: Hammer.INPUT_MOVE,
isFirst: true,
});
}
forceInvalidate(event) {
super.forceInvalidate(event);
clearTimeout(this.visualFeedbackTimer);
this.visualFeedbackTimer = null;
this.initialEvent = null;
}
onRawEvent(ev) {
super.onRawEvent(ev);
if (ev.isFinal && this.isGestureRunning) {
let timeout;
if (this.visualFeedbackTimer) {
// Aesthetic timing for a quick tap.
// We haven't activated the tap right away to emulate iOS `delaysContentTouches`
// Now we must send the initial activation event and wait a set amount of time before firing the end event.
timeout = CONTENT_TOUCHES_QUICK_TAP_END_DELAY;
this.sendGestureStartedEvent(this.initialEvent);
this.initialEvent = null;
}
fireAfterInterval(() => {
this.sendEvent({
...ev,
eventType: Hammer.INPUT_END,
isFinal: true,
});
this.onGestureEnded();
}, timeout);
}
}
updateGestureConfig({
shouldActivateOnStart = false,
disallowInterruption = false,
shouldCancelWhenOutside = true,
minDurationMs = Number.NaN,
maxDist = Number.NaN,
minPointers = 1,
maxPointers = 1,
...props
}) {
return super.updateGestureConfig({
shouldActivateOnStart,
disallowInterruption,
shouldCancelWhenOutside,
minDurationMs,
maxDist,
minPointers,
maxPointers,
...props,
});
}
}
export default PressGestureHandler;