cione-comp-lib
Version:
`$ yarn add cione-comp-lib` 或者 `$ npm i cione-comp-lib -S`
488 lines (487 loc) • 16 kB
JavaScript
import { __exports as gesturehandler } from "../../../../../_virtual/gesturehandler.mjs";
(function(exports) {
Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = void 0;
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor)
descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps)
_defineProperties(Constructor.prototype, protoProps);
if (staticProps)
_defineProperties(Constructor, staticProps);
return Constructor;
}
var GH_NOGESTURE = 0;
var GH_ONETAP = 1;
var GH_TWOTAP = 2;
var GH_THREETAP = 4;
var GH_DRAG = 8;
var GH_LONGPRESS = 16;
var GH_TWODRAG = 32;
var GH_PINCH = 64;
var GH_INITSTATE = 127;
var GH_MOVE_THRESHOLD = 50;
var GH_ANGLE_THRESHOLD = 90;
var GH_MULTITOUCH_TIMEOUT = 250;
var GH_TAP_TIMEOUT = 1e3;
var GH_LONGPRESS_TIMEOUT = 1e3;
var GH_TWOTOUCH_TIMEOUT = 50;
var GestureHandler = /* @__PURE__ */ function() {
function GestureHandler2() {
_classCallCheck(this, GestureHandler2);
this._target = null;
this._state = GH_INITSTATE;
this._tracked = [];
this._ignored = [];
this._waitingRelease = false;
this._releaseStart = 0;
this._longpressTimeoutId = null;
this._twoTouchTimeoutId = null;
this._boundEventHandler = this._eventHandler.bind(this);
}
_createClass(GestureHandler2, [{
key: "attach",
value: function attach(target) {
this.detach();
this._target = target;
this._target.addEventListener("touchstart", this._boundEventHandler);
this._target.addEventListener("touchmove", this._boundEventHandler);
this._target.addEventListener("touchend", this._boundEventHandler);
this._target.addEventListener("touchcancel", this._boundEventHandler);
}
}, {
key: "detach",
value: function detach() {
if (!this._target) {
return;
}
this._stopLongpressTimeout();
this._stopTwoTouchTimeout();
this._target.removeEventListener("touchstart", this._boundEventHandler);
this._target.removeEventListener("touchmove", this._boundEventHandler);
this._target.removeEventListener("touchend", this._boundEventHandler);
this._target.removeEventListener("touchcancel", this._boundEventHandler);
this._target = null;
}
}, {
key: "_eventHandler",
value: function _eventHandler(e) {
var fn;
e.stopPropagation();
e.preventDefault();
switch (e.type) {
case "touchstart":
fn = this._touchStart;
break;
case "touchmove":
fn = this._touchMove;
break;
case "touchend":
case "touchcancel":
fn = this._touchEnd;
break;
}
for (var i = 0; i < e.changedTouches.length; i++) {
var touch = e.changedTouches[i];
fn.call(this, touch.identifier, touch.clientX, touch.clientY);
}
}
}, {
key: "_touchStart",
value: function _touchStart(id, x, y) {
if (this._hasDetectedGesture() || this._state === GH_NOGESTURE) {
this._ignored.push(id);
return;
}
if (this._tracked.length > 0 && Date.now() - this._tracked[0].started > GH_MULTITOUCH_TIMEOUT) {
this._state = GH_NOGESTURE;
this._ignored.push(id);
return;
}
if (this._waitingRelease) {
this._state = GH_NOGESTURE;
this._ignored.push(id);
return;
}
this._tracked.push({
id,
started: Date.now(),
active: true,
firstX: x,
firstY: y,
lastX: x,
lastY: y,
angle: 0
});
switch (this._tracked.length) {
case 1:
this._startLongpressTimeout();
break;
case 2:
this._state &= ~(GH_ONETAP | GH_DRAG | GH_LONGPRESS);
this._stopLongpressTimeout();
break;
case 3:
this._state &= ~(GH_TWOTAP | GH_TWODRAG | GH_PINCH);
break;
default:
this._state = GH_NOGESTURE;
}
}
}, {
key: "_touchMove",
value: function _touchMove(id, x, y) {
var touch = this._tracked.find(function(t) {
return t.id === id;
});
if (touch === void 0) {
return;
}
touch.lastX = x;
touch.lastY = y;
var deltaX = x - touch.firstX;
var deltaY = y - touch.firstY;
if (touch.firstX !== touch.lastX || touch.firstY !== touch.lastY) {
touch.angle = Math.atan2(deltaY, deltaX) * 180 / Math.PI;
}
if (!this._hasDetectedGesture()) {
if (Math.hypot(deltaX, deltaY) < GH_MOVE_THRESHOLD) {
return;
}
this._state &= ~(GH_ONETAP | GH_TWOTAP | GH_THREETAP | GH_LONGPRESS);
this._stopLongpressTimeout();
if (this._tracked.length !== 1) {
this._state &= ~GH_DRAG;
}
if (this._tracked.length !== 2) {
this._state &= ~(GH_TWODRAG | GH_PINCH);
}
if (this._tracked.length === 2) {
var prevTouch = this._tracked.find(function(t) {
return t.id !== id;
});
var prevDeltaMove = Math.hypot(prevTouch.firstX - prevTouch.lastX, prevTouch.firstY - prevTouch.lastY);
if (prevDeltaMove > GH_MOVE_THRESHOLD) {
var deltaAngle = Math.abs(touch.angle - prevTouch.angle);
deltaAngle = Math.abs((deltaAngle + 180) % 360 - 180);
if (deltaAngle > GH_ANGLE_THRESHOLD) {
this._state &= ~GH_TWODRAG;
} else {
this._state &= ~GH_PINCH;
}
if (this._isTwoTouchTimeoutRunning()) {
this._stopTwoTouchTimeout();
}
} else if (!this._isTwoTouchTimeoutRunning()) {
this._startTwoTouchTimeout();
}
}
if (!this._hasDetectedGesture()) {
return;
}
this._pushEvent("gesturestart");
}
this._pushEvent("gesturemove");
}
}, {
key: "_touchEnd",
value: function _touchEnd(id, x, y) {
if (this._ignored.indexOf(id) !== -1) {
this._ignored.splice(this._ignored.indexOf(id), 1);
if (this._ignored.length === 0 && this._tracked.length === 0) {
this._state = GH_INITSTATE;
this._waitingRelease = false;
}
return;
}
if (!this._hasDetectedGesture() && this._isTwoTouchTimeoutRunning()) {
this._stopTwoTouchTimeout();
this._state = GH_NOGESTURE;
}
if (!this._hasDetectedGesture()) {
this._state &= ~(GH_DRAG | GH_TWODRAG | GH_PINCH);
this._state &= ~GH_LONGPRESS;
this._stopLongpressTimeout();
if (!this._waitingRelease) {
this._releaseStart = Date.now();
this._waitingRelease = true;
switch (this._tracked.length) {
case 1:
this._state &= ~(GH_TWOTAP | GH_THREETAP);
break;
case 2:
this._state &= ~(GH_ONETAP | GH_THREETAP);
break;
}
}
}
if (this._waitingRelease) {
if (Date.now() - this._releaseStart > GH_MULTITOUCH_TIMEOUT) {
this._state = GH_NOGESTURE;
}
if (this._tracked.some(function(t) {
return Date.now() - t.started > GH_TAP_TIMEOUT;
})) {
this._state = GH_NOGESTURE;
}
var touch = this._tracked.find(function(t) {
return t.id === id;
});
touch.active = false;
if (this._hasDetectedGesture()) {
this._pushEvent("gesturestart");
} else {
if (this._state !== GH_NOGESTURE) {
return;
}
}
}
if (this._hasDetectedGesture()) {
this._pushEvent("gestureend");
}
for (var i = 0; i < this._tracked.length; i++) {
if (this._tracked[i].active) {
this._ignored.push(this._tracked[i].id);
}
}
this._tracked = [];
this._state = GH_NOGESTURE;
if (this._ignored.indexOf(id) !== -1) {
this._ignored.splice(this._ignored.indexOf(id), 1);
}
if (this._ignored.length === 0) {
this._state = GH_INITSTATE;
this._waitingRelease = false;
}
}
}, {
key: "_hasDetectedGesture",
value: function _hasDetectedGesture() {
if (this._state === GH_NOGESTURE) {
return false;
}
if (this._state & this._state - 1) {
return false;
}
if (this._state & (GH_ONETAP | GH_TWOTAP | GH_THREETAP)) {
if (this._tracked.some(function(t) {
return t.active;
})) {
return false;
}
}
return true;
}
}, {
key: "_startLongpressTimeout",
value: function _startLongpressTimeout() {
var _this = this;
this._stopLongpressTimeout();
this._longpressTimeoutId = setTimeout(function() {
return _this._longpressTimeout();
}, GH_LONGPRESS_TIMEOUT);
}
}, {
key: "_stopLongpressTimeout",
value: function _stopLongpressTimeout() {
clearTimeout(this._longpressTimeoutId);
this._longpressTimeoutId = null;
}
}, {
key: "_longpressTimeout",
value: function _longpressTimeout() {
if (this._hasDetectedGesture()) {
throw new Error("A longpress gesture failed, conflict with a different gesture");
}
this._state = GH_LONGPRESS;
this._pushEvent("gesturestart");
}
}, {
key: "_startTwoTouchTimeout",
value: function _startTwoTouchTimeout() {
var _this2 = this;
this._stopTwoTouchTimeout();
this._twoTouchTimeoutId = setTimeout(function() {
return _this2._twoTouchTimeout();
}, GH_TWOTOUCH_TIMEOUT);
}
}, {
key: "_stopTwoTouchTimeout",
value: function _stopTwoTouchTimeout() {
clearTimeout(this._twoTouchTimeoutId);
this._twoTouchTimeoutId = null;
}
}, {
key: "_isTwoTouchTimeoutRunning",
value: function _isTwoTouchTimeoutRunning() {
return this._twoTouchTimeoutId !== null;
}
}, {
key: "_twoTouchTimeout",
value: function _twoTouchTimeout() {
if (this._tracked.length === 0) {
throw new Error("A pinch or two drag gesture failed, no tracked touches");
}
var avgM = this._getAverageMovement();
var avgMoveH = Math.abs(avgM.x);
var avgMoveV = Math.abs(avgM.y);
var avgD = this._getAverageDistance();
var deltaTouchDistance = Math.abs(Math.hypot(avgD.first.x, avgD.first.y) - Math.hypot(avgD.last.x, avgD.last.y));
if (avgMoveV < deltaTouchDistance && avgMoveH < deltaTouchDistance) {
this._state = GH_PINCH;
} else {
this._state = GH_TWODRAG;
}
this._pushEvent("gesturestart");
this._pushEvent("gesturemove");
}
}, {
key: "_pushEvent",
value: function _pushEvent(type) {
var detail = {
type: this._stateToGesture(this._state)
};
var avg = this._getPosition();
var pos = avg.last;
if (type === "gesturestart") {
pos = avg.first;
}
switch (this._state) {
case GH_TWODRAG:
case GH_PINCH:
pos = avg.first;
break;
}
detail["clientX"] = pos.x;
detail["clientY"] = pos.y;
if (this._state === GH_PINCH) {
var distance = this._getAverageDistance();
if (type === "gesturestart") {
detail["magnitudeX"] = distance.first.x;
detail["magnitudeY"] = distance.first.y;
} else {
detail["magnitudeX"] = distance.last.x;
detail["magnitudeY"] = distance.last.y;
}
} else if (this._state === GH_TWODRAG) {
if (type === "gesturestart") {
detail["magnitudeX"] = 0;
detail["magnitudeY"] = 0;
} else {
var movement = this._getAverageMovement();
detail["magnitudeX"] = movement.x;
detail["magnitudeY"] = movement.y;
}
}
var gev = new CustomEvent(type, {
detail
});
this._target.dispatchEvent(gev);
}
}, {
key: "_stateToGesture",
value: function _stateToGesture(state) {
switch (state) {
case GH_ONETAP:
return "onetap";
case GH_TWOTAP:
return "twotap";
case GH_THREETAP:
return "threetap";
case GH_DRAG:
return "drag";
case GH_LONGPRESS:
return "longpress";
case GH_TWODRAG:
return "twodrag";
case GH_PINCH:
return "pinch";
}
throw new Error("Unknown gesture state: " + state);
}
}, {
key: "_getPosition",
value: function _getPosition() {
if (this._tracked.length === 0) {
throw new Error("Failed to get gesture position, no tracked touches");
}
var size = this._tracked.length;
var fx = 0, fy = 0, lx = 0, ly = 0;
for (var i = 0; i < this._tracked.length; i++) {
fx += this._tracked[i].firstX;
fy += this._tracked[i].firstY;
lx += this._tracked[i].lastX;
ly += this._tracked[i].lastY;
}
return {
first: {
x: fx / size,
y: fy / size
},
last: {
x: lx / size,
y: ly / size
}
};
}
}, {
key: "_getAverageMovement",
value: function _getAverageMovement() {
if (this._tracked.length === 0) {
throw new Error("Failed to get gesture movement, no tracked touches");
}
var totalH, totalV;
totalH = totalV = 0;
var size = this._tracked.length;
for (var i = 0; i < this._tracked.length; i++) {
totalH += this._tracked[i].lastX - this._tracked[i].firstX;
totalV += this._tracked[i].lastY - this._tracked[i].firstY;
}
return {
x: totalH / size,
y: totalV / size
};
}
}, {
key: "_getAverageDistance",
value: function _getAverageDistance() {
if (this._tracked.length === 0) {
throw new Error("Failed to get gesture distance, no tracked touches");
}
var first = this._tracked[0];
var last = this._tracked[this._tracked.length - 1];
var fdx = Math.abs(last.firstX - first.firstX);
var fdy = Math.abs(last.firstY - first.firstY);
var ldx = Math.abs(last.lastX - first.lastX);
var ldy = Math.abs(last.lastY - first.lastY);
return {
first: {
x: fdx,
y: fdy
},
last: {
x: ldx,
y: ldy
}
};
}
}]);
return GestureHandler2;
}();
exports["default"] = GestureHandler;
})(gesturehandler);