@gdjiami/hooks
Version:
react hooks for mygzb.com
184 lines (183 loc) • 8.29 kB
JavaScript
import { __assign, __read } from "tslib";
import { useRef, useEffect } from 'react';
import { TOUCH_SUPPROTED, extraPositions, isMouseEvent } from './utils';
import useInstance from './useInstance';
import useRefState from './useRefState';
/**
* 获取抽象化的mouse/touch事件. 支持多点触摸
* TODO: 可配mouse
* TODO: pasive
* TODO: 过滤
* @param options
*/
export default function useMultiTouchGesture(options) {
var el = options.ref || useRef();
var _a = __read(useRefState(false), 3), interacting = _a[0], setInteracting = _a[1], refInteracting = _a[2];
var _b = __read(useInstance({
touches: new Map(),
}), 1), state = _b[0];
useEffect(function () {
var getTouches = function () {
return Array.from(state.touches.values());
};
var handleActionStart = function (event) {
var coords = extraPositions(event);
if (coords.length === 0) {
return;
}
var changedTouches = coords.map(function (i) { return (__assign(__assign({}, i), { timestamp: Date.now(), target: el.current, delta: 0, deltaX: 0, deltaY: 0, distance: 0, distanceX: 0, distanceY: 0, velocity: 0 })); });
if (options.onDown != null &&
options.onDown({
touches: getTouches().concat(changedTouches),
changedTouches: changedTouches,
}) === false) {
// prevented
return;
}
event.stopPropagation();
event.preventDefault();
// save
changedTouches.forEach(function (i) {
state.touches.set(i.id, __assign(__assign({}, i), { start: i, previous: i }));
});
if (options.onAction) {
options.onAction(getTouches());
}
if (refInteracting.current) {
return;
}
setInteracting(true);
/**
* 处理移动
*/
var handleActionMove = function (event) {
if (!isMouseEvent(event)) {
event.preventDefault();
}
var coords = extraPositions(event);
if (coords.length === 0) {
return;
}
var changedTouches = coords
.map(function (pos) {
var savedTouch = state.touches.get(pos.id);
if (savedTouch == null) {
return null;
}
var start = savedTouch.start;
var last = savedTouch;
var deltaX = pos.pageX - last.pageX;
var deltaY = pos.pageY - last.pageY;
var delta = Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
var distanceX = pos.pageX - start.pageX;
var distanceY = pos.pageY - start.pageY;
var distance = Math.sqrt(Math.pow(distanceX, 2) + Math.pow(distanceY, 2));
var timestamp = Date.now();
var velocity = delta / (timestamp - last.timestamp);
return __assign(__assign(__assign({}, savedTouch), pos), { previous: savedTouch, timestamp: timestamp,
deltaX: deltaX,
deltaY: deltaY,
delta: delta,
distanceX: distanceX,
distanceY: distanceY,
distance: distance,
velocity: velocity });
})
.filter(function (i) { return !!i; });
changedTouches.forEach(function (touch) {
state.touches.set(touch.id, touch);
});
if (options.onMove) {
options.onMove({
changedTouches: changedTouches,
touches: getTouches(),
});
}
if (options.onAction) {
options.onAction(getTouches());
}
};
if (isMouseEvent(event)) {
// mouse drive
var clean = function (event) {
// 鼠标事件只能有一个
document.removeEventListener('mousemove', handleActionMove);
if (!refInteracting.current) {
return;
}
var pos = extraPositions(event);
var savedTouch = state.touches.get(pos[0].id);
var changedTouches = [
__assign(__assign(__assign({}, savedTouch), pos[0]), { previous: savedTouch, timestamp: Date.now() }),
];
setInteracting(false);
state.touches.clear();
state.touches.delete(pos[0].id);
if (options.onUp) {
options.onUp({
touches: [],
changedTouches: changedTouches,
});
}
if (options.onAction) {
options.onAction([]);
}
};
document.addEventListener('mousemove', handleActionMove);
document.addEventListener('mouseup', clean, { once: true });
document.addEventListener('mouseleave', clean, { once: true });
}
else {
// touch drive
var removeListener_1 = function () {
el.current.removeEventListener('touchmove', handleActionMove);
el.current.removeEventListener('touchend', clean_1);
el.current.removeEventListener('touchcancel', clean_1);
state.touches.clear();
};
var clean_1 = function (event) {
if (!refInteracting.current) {
removeListener_1();
return;
}
var coods = extraPositions(event);
if (coods.length === 0) {
return;
}
var changedTouches = coods
.map(function (pos) {
var savedTouch = state.touches.get(pos.id);
if (savedTouch === null) {
return null;
}
return __assign(__assign(__assign({}, savedTouch), pos), { previous: savedTouch, timestamp: Date.now() });
})
.filter(function (i) { return !!i; });
changedTouches.forEach(function (i) {
state.touches.delete(i.id);
});
var currentTouches = getTouches();
if (options.onUp) {
options.onUp({ touches: currentTouches, changedTouches: changedTouches });
}
if (currentTouches.length === 0) {
removeListener_1();
setInteracting(false);
}
};
el.current.addEventListener('touchmove', handleActionMove);
el.current.addEventListener('touchend', clean_1);
el.current.addEventListener('touchcancel', clean_1);
}
};
var useTouch = TOUCH_SUPPROTED;
el.current.addEventListener('mousedown', handleActionStart);
useTouch && el.current.addEventListener('touchstart', handleActionStart);
return function () {
el.current.removeEventListener('mousedown', handleActionStart);
useTouch &&
el.current.removeEventListener('touchstart', handleActionStart);
};
}, []);
return { ref: el, interacting: interacting };
}