@gdjiami/hooks
Version:
react hooks for mygzb.com
115 lines (114 loc) • 5.31 kB
JavaScript
import { __assign, __read } from "tslib";
import { useRef, useEffect } from 'react';
import { TOUCH_SUPPROTED, extraPosition, isMouseEvent, } from './utils';
import useInstance from './useInstance';
import useRefState from './useRefState';
/**
* 获取抽象化的mouse/touch事件
* TODO: pasive
* @param options
*/
export default function useGesture(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({}), 2), state = _b[0], updateState = _b[1];
useEffect(function () {
var handleActionStart = function (event) {
var pos = extraPosition(event);
if (pos == null) {
return;
}
var coord = __assign(__assign({}, pos), { 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(coord) === false) {
// prevented
return;
}
event.stopPropagation();
event.preventDefault();
if (options.onAction) {
options.onAction({ down: true, first: true, coordinate: coord });
}
updateState({ start: coord, last: coord });
setInteracting(true);
/**
* 处理移动
*/
var handleActionMove = function (event) {
if (!isMouseEvent(event)) {
event.preventDefault();
}
var pos = extraPosition(event, state.start && state.start.id);
if (pos == null) {
return;
}
var start = state.start;
var last = state.last;
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 coord = __assign(__assign({}, pos), { start: start, previous: last, timestamp: timestamp,
deltaX: deltaX,
deltaY: deltaY,
delta: delta,
distanceX: distanceX,
distanceY: distanceY,
distance: distance, velocity: delta / (timestamp - last.timestamp), target: el.current });
if (options.onMove) {
options.onMove(coord);
}
if (options.onAction) {
options.onAction({ down: true, first: false, coordinate: coord });
}
updateState({ last: coord });
};
/**
* 动作结束
*/
var handleActionEnd = function (event) {
if (!refInteracting.current) {
return;
}
var pos = extraPosition(event, state.start && state.start.id);
var coord = __assign(__assign(__assign({}, state.last), pos), { timestamp: Date.now(), target: el.current, start: state.start, last: state.last });
setInteracting(false);
if (options.onUp) {
options.onUp(coord);
}
if (options.onAction) {
options.onAction({ down: false, first: false, coordinate: coord });
}
};
if (isMouseEvent(event)) {
var clean = function (event) {
document.removeEventListener('mousemove', handleActionMove);
handleActionEnd(event);
};
document.addEventListener('mousemove', handleActionMove);
document.addEventListener('mouseup', clean, { once: true });
document.addEventListener('mouseleave', clean, { once: true });
}
else {
var clean = function (event) {
el.current.removeEventListener('touchmove', handleActionMove);
handleActionEnd(event);
};
el.current.addEventListener('touchmove', handleActionMove);
el.current.addEventListener('touchend', clean, { once: true });
el.current.addEventListener('touchcancel', clean, { once: true });
}
};
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 };
}