@gdjiami/hooks
Version:
react hooks for mygzb.com
195 lines (166 loc) • 5.04 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
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 _useRefState = useRefState(false),
interacting = _useRefState[0],
setInteracting = _useRefState[1],
refInteracting = _useRefState[2];
var _useInstance = useInstance({}),
state = _useInstance[0],
updateState = _useInstance[1];
useEffect(function () {
var handleActionStart = function handleActionStart(event) {
var pos = extraPosition(event);
if (pos == null) {
return;
}
var coord = _extends({}, 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 handleActionMove(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 = _extends({}, 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 handleActionEnd(event) {
if (!refInteracting.current) {
return;
}
var pos = extraPosition(event, state.start && state.start.id);
var coord = _extends({}, 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 clean(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 _clean(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
};
}