react-native-gesture-handler
Version:
Declarative API exposing native platform touch and gesture system to React Native
514 lines (402 loc) • 15.2 kB
JavaScript
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
import { State } from '../../State';
import { DEFAULT_TOUCH_SLOP } from '../constants';
import { WheelDevice } from '../interfaces';
import GestureHandler from './GestureHandler';
const DEFAULT_MIN_POINTERS = 1;
const DEFAULT_MAX_POINTERS = 10;
const DEFAULT_MIN_DIST_SQ = DEFAULT_TOUCH_SLOP * DEFAULT_TOUCH_SLOP;
export default class PanGestureHandler extends GestureHandler {
constructor(...args) {
super(...args);
_defineProperty(this, "customActivationProperties", ['activeOffsetXStart', 'activeOffsetXEnd', 'failOffsetXStart', 'failOffsetXEnd', 'activeOffsetYStart', 'activeOffsetYEnd', 'failOffsetYStart', 'failOffsetYEnd', 'minVelocityX', 'minVelocityY', 'minVelocity']);
_defineProperty(this, "velocityX", 0);
_defineProperty(this, "velocityY", 0);
_defineProperty(this, "minDistSq", DEFAULT_MIN_DIST_SQ);
_defineProperty(this, "activeOffsetXStart", -Number.MAX_SAFE_INTEGER);
_defineProperty(this, "activeOffsetXEnd", Number.MIN_SAFE_INTEGER);
_defineProperty(this, "failOffsetXStart", Number.MIN_SAFE_INTEGER);
_defineProperty(this, "failOffsetXEnd", Number.MAX_SAFE_INTEGER);
_defineProperty(this, "activeOffsetYStart", Number.MAX_SAFE_INTEGER);
_defineProperty(this, "activeOffsetYEnd", Number.MIN_SAFE_INTEGER);
_defineProperty(this, "failOffsetYStart", Number.MIN_SAFE_INTEGER);
_defineProperty(this, "failOffsetYEnd", Number.MAX_SAFE_INTEGER);
_defineProperty(this, "minVelocityX", Number.MAX_SAFE_INTEGER);
_defineProperty(this, "minVelocityY", Number.MAX_SAFE_INTEGER);
_defineProperty(this, "minVelocitySq", Number.MAX_SAFE_INTEGER);
_defineProperty(this, "minPointers", DEFAULT_MIN_POINTERS);
_defineProperty(this, "maxPointers", DEFAULT_MAX_POINTERS);
_defineProperty(this, "startX", 0);
_defineProperty(this, "startY", 0);
_defineProperty(this, "offsetX", 0);
_defineProperty(this, "offsetY", 0);
_defineProperty(this, "lastX", 0);
_defineProperty(this, "lastY", 0);
_defineProperty(this, "stylusData", void 0);
_defineProperty(this, "activateAfterLongPress", 0);
_defineProperty(this, "activationTimeout", 0);
_defineProperty(this, "enableTrackpadTwoFingerGesture", false);
_defineProperty(this, "endWheelTimeout", 0);
_defineProperty(this, "wheelDevice", WheelDevice.UNDETERMINED);
}
updateGestureConfig({
enabled = true,
...props
}) {
this.resetConfig();
super.updateGestureConfig({
enabled: enabled,
...props
});
this.checkCustomActivationCriteria(this.customActivationProperties);
if (this.config.minDist !== undefined) {
this.minDistSq = this.config.minDist * this.config.minDist;
} else if (this.hasCustomActivationCriteria) {
this.minDistSq = Number.MAX_SAFE_INTEGER;
}
if (this.config.minPointers !== undefined) {
this.minPointers = this.config.minPointers;
}
if (this.config.maxPointers !== undefined) {
this.maxPointers = this.config.maxPointers;
}
if (this.config.minVelocity !== undefined) {
this.minVelocityX = this.config.minVelocity;
this.minVelocityY = this.config.minVelocity;
}
if (this.config.minVelocityX !== undefined) {
this.minVelocityX = this.config.minVelocityX;
}
if (this.config.minVelocityY !== undefined) {
this.minVelocityY = this.config.minVelocityY;
}
if (this.config.activateAfterLongPress !== undefined) {
this.activateAfterLongPress = this.config.activateAfterLongPress;
}
if (this.config.activeOffsetXStart !== undefined) {
this.activeOffsetXStart = this.config.activeOffsetXStart;
if (this.config.activeOffsetXEnd === undefined) {
this.activeOffsetXEnd = Number.MAX_SAFE_INTEGER;
}
}
if (this.config.activeOffsetXEnd !== undefined) {
this.activeOffsetXEnd = this.config.activeOffsetXEnd;
if (this.config.activeOffsetXStart === undefined) {
this.activeOffsetXStart = Number.MIN_SAFE_INTEGER;
}
}
if (this.config.failOffsetXStart !== undefined) {
this.failOffsetXStart = this.config.failOffsetXStart;
if (this.config.failOffsetXEnd === undefined) {
this.failOffsetXEnd = Number.MAX_SAFE_INTEGER;
}
}
if (this.config.failOffsetXEnd !== undefined) {
this.failOffsetXEnd = this.config.failOffsetXEnd;
if (this.config.failOffsetXStart === undefined) {
this.failOffsetXStart = Number.MIN_SAFE_INTEGER;
}
}
if (this.config.activeOffsetYStart !== undefined) {
this.activeOffsetYStart = this.config.activeOffsetYStart;
if (this.config.activeOffsetYEnd === undefined) {
this.activeOffsetYEnd = Number.MAX_SAFE_INTEGER;
}
}
if (this.config.activeOffsetYEnd !== undefined) {
this.activeOffsetYEnd = this.config.activeOffsetYEnd;
if (this.config.activeOffsetYStart === undefined) {
this.activeOffsetYStart = Number.MIN_SAFE_INTEGER;
}
}
if (this.config.failOffsetYStart !== undefined) {
this.failOffsetYStart = this.config.failOffsetYStart;
if (this.config.failOffsetYEnd === undefined) {
this.failOffsetYEnd = Number.MAX_SAFE_INTEGER;
}
}
if (this.config.failOffsetYEnd !== undefined) {
this.failOffsetYEnd = this.config.failOffsetYEnd;
if (this.config.failOffsetYStart === undefined) {
this.failOffsetYStart = Number.MIN_SAFE_INTEGER;
}
}
if (this.config.enableTrackpadTwoFingerGesture !== undefined) {
this.enableTrackpadTwoFingerGesture = this.config.enableTrackpadTwoFingerGesture;
}
}
resetConfig() {
super.resetConfig();
this.activeOffsetXStart = -Number.MAX_SAFE_INTEGER;
this.activeOffsetXEnd = Number.MIN_SAFE_INTEGER;
this.failOffsetXStart = Number.MIN_SAFE_INTEGER;
this.failOffsetXEnd = Number.MAX_SAFE_INTEGER;
this.activeOffsetYStart = Number.MAX_SAFE_INTEGER;
this.activeOffsetYEnd = Number.MIN_SAFE_INTEGER;
this.failOffsetYStart = Number.MIN_SAFE_INTEGER;
this.failOffsetYEnd = Number.MAX_SAFE_INTEGER;
this.minVelocityX = Number.MAX_SAFE_INTEGER;
this.minVelocityY = Number.MAX_SAFE_INTEGER;
this.minVelocitySq = Number.MAX_SAFE_INTEGER;
this.minDistSq = DEFAULT_MIN_DIST_SQ;
this.minPointers = DEFAULT_MIN_POINTERS;
this.maxPointers = DEFAULT_MAX_POINTERS;
this.activateAfterLongPress = 0;
}
transformNativeEvent() {
const translationX = this.getTranslationX();
const translationY = this.getTranslationY();
return { ...super.transformNativeEvent(),
translationX: isNaN(translationX) ? 0 : translationX,
translationY: isNaN(translationY) ? 0 : translationY,
velocityX: this.velocityX,
velocityY: this.velocityY,
stylusData: this.stylusData
};
}
getTranslationX() {
return this.lastX - this.startX + this.offsetX;
}
getTranslationY() {
return this.lastY - this.startY + this.offsetY;
}
clearActivationTimeout() {
clearTimeout(this.activationTimeout);
} // Events Handling
onPointerDown(event) {
if (!this.isButtonInConfig(event.button)) {
return;
}
this.tracker.addToTracker(event);
this.stylusData = event.stylusData;
super.onPointerDown(event);
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
this.startX = this.lastX;
this.startY = this.lastY;
this.tryBegin(event);
this.checkBegan();
this.tryToSendTouchEvent(event);
}
onPointerAdd(event) {
this.tracker.addToTracker(event);
super.onPointerAdd(event);
this.tryBegin(event);
this.offsetX += this.lastX - this.startX;
this.offsetY += this.lastY - this.startY;
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
this.startX = this.lastX;
this.startY = this.lastY;
if (this.tracker.getTrackedPointersCount() > this.maxPointers) {
if (this.currentState === State.ACTIVE) {
this.cancel();
} else {
this.fail();
}
} else {
this.checkBegan();
}
}
onPointerUp(event) {
this.stylusData = event.stylusData;
super.onPointerUp(event);
if (this.currentState === State.ACTIVE) {
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
}
this.tracker.removeFromTracker(event.pointerId);
if (this.tracker.getTrackedPointersCount() === 0) {
this.clearActivationTimeout();
}
if (this.currentState === State.ACTIVE) {
this.end();
} else {
this.resetProgress();
this.fail();
}
}
onPointerRemove(event) {
super.onPointerRemove(event);
this.tracker.removeFromTracker(event.pointerId);
this.offsetX += this.lastX - this.startX;
this.offsetY += this.lastY - this.startY;
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
this.startX = this.lastX;
this.startY = this.lastY;
if (!(this.currentState === State.ACTIVE && this.tracker.getTrackedPointersCount() < this.minPointers)) {
this.checkBegan();
}
}
onPointerMove(event) {
this.tracker.track(event);
this.stylusData = event.stylusData;
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
const velocity = this.tracker.getVelocity(event.pointerId);
this.velocityX = velocity.x;
this.velocityY = velocity.y;
this.checkBegan();
super.onPointerMove(event);
}
onPointerOutOfBounds(event) {
if (this.getShouldCancelWhenOutside()) {
return;
}
this.tracker.track(event);
this.stylusData = event.stylusData;
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
const velocity = this.tracker.getVelocity(event.pointerId);
this.velocityX = velocity.x;
this.velocityY = velocity.y;
this.checkBegan();
if (this.currentState === State.ACTIVE) {
super.onPointerOutOfBounds(event);
}
}
scheduleWheelEnd(event) {
clearTimeout(this.endWheelTimeout);
this.endWheelTimeout = setTimeout(() => {
if (this.currentState === State.ACTIVE) {
this.end();
this.tracker.removeFromTracker(event.pointerId);
this.currentState = State.UNDETERMINED;
}
this.wheelDevice = WheelDevice.UNDETERMINED;
}, 30);
}
onWheel(event) {
if (this.wheelDevice === WheelDevice.MOUSE || !this.enableTrackpadTwoFingerGesture) {
return;
}
if (this.currentState === State.UNDETERMINED) {
this.wheelDevice = event.wheelDeltaY % 120 !== 0 ? WheelDevice.TOUCHPAD : WheelDevice.MOUSE;
if (this.wheelDevice === WheelDevice.MOUSE) {
this.scheduleWheelEnd(event);
return;
}
this.tracker.addToTracker(event);
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
this.startX = this.lastX;
this.startY = this.lastY;
this.begin();
this.activate();
}
this.tracker.track(event);
const lastCoords = this.tracker.getAbsoluteCoordsAverage();
this.lastX = lastCoords.x;
this.lastY = lastCoords.y;
const velocity = this.tracker.getVelocity(event.pointerId);
this.velocityX = velocity.x;
this.velocityY = velocity.y;
this.tryToSendMoveEvent(false, event);
this.scheduleWheelEnd(event);
}
shouldActivate() {
const dx = this.getTranslationX();
if (this.activeOffsetXStart !== Number.MAX_SAFE_INTEGER && dx < this.activeOffsetXStart) {
return true;
}
if (this.activeOffsetXEnd !== Number.MIN_SAFE_INTEGER && dx > this.activeOffsetXEnd) {
return true;
}
const dy = this.getTranslationY();
if (this.activeOffsetYStart !== Number.MAX_SAFE_INTEGER && dy < this.activeOffsetYStart) {
return true;
}
if (this.activeOffsetYEnd !== Number.MIN_SAFE_INTEGER && dy > this.activeOffsetYEnd) {
return true;
}
const distanceSq = dx * dx + dy * dy;
if (this.minDistSq !== Number.MAX_SAFE_INTEGER && distanceSq >= this.minDistSq) {
return true;
}
const vx = this.velocityX;
if (this.minVelocityX !== Number.MAX_SAFE_INTEGER && (this.minVelocityX < 0 && vx <= this.minVelocityX || this.minVelocityX >= 0 && this.minVelocityX <= vx)) {
return true;
}
const vy = this.velocityY;
if (this.minVelocityY !== Number.MAX_SAFE_INTEGER && (this.minVelocityY < 0 && vy <= this.minVelocityY || this.minVelocityY >= 0 && this.minVelocityY <= vy)) {
return true;
}
const velocitySq = vx * vx + vy * vy;
return this.minVelocitySq !== Number.MAX_SAFE_INTEGER && velocitySq >= this.minVelocitySq;
}
shouldFail() {
const dx = this.getTranslationX();
const dy = this.getTranslationY();
const distanceSq = dx * dx + dy * dy;
if (this.activateAfterLongPress > 0 && distanceSq > DEFAULT_MIN_DIST_SQ) {
this.clearActivationTimeout();
return true;
}
if (this.failOffsetXStart !== Number.MIN_SAFE_INTEGER && dx < this.failOffsetXStart) {
return true;
}
if (this.failOffsetXEnd !== Number.MAX_SAFE_INTEGER && dx > this.failOffsetXEnd) {
return true;
}
if (this.failOffsetYStart !== Number.MIN_SAFE_INTEGER && dy < this.failOffsetYStart) {
return true;
}
return this.failOffsetYEnd !== Number.MAX_SAFE_INTEGER && dy > this.failOffsetYEnd;
}
tryBegin(event) {
if (this.currentState === State.UNDETERMINED && this.tracker.getTrackedPointersCount() >= this.minPointers) {
this.resetProgress();
this.offsetX = 0;
this.offsetY = 0;
this.velocityX = 0;
this.velocityY = 0;
this.begin();
if (this.activateAfterLongPress > 0) {
this.activationTimeout = setTimeout(() => {
this.activate();
}, this.activateAfterLongPress);
}
} else {
const velocity = this.tracker.getVelocity(event.pointerId);
this.velocityX = velocity.x;
this.velocityY = velocity.y;
}
}
checkBegan() {
if (this.currentState === State.BEGAN) {
if (this.shouldFail()) {
this.fail();
} else if (this.shouldActivate()) {
this.activate();
}
}
}
activate(force = false) {
if (this.currentState !== State.ACTIVE) {
this.resetProgress();
}
super.activate(force);
}
onCancel() {
this.clearActivationTimeout();
}
onReset() {
this.clearActivationTimeout();
}
resetProgress() {
if (this.currentState === State.ACTIVE) {
return;
}
this.startX = this.lastX;
this.startY = this.lastY;
}
}
//# sourceMappingURL=PanGestureHandler.js.map