@react-vant-next/campaign
Version:
React Mobile UI Components based on Vant UI - Next Generation
119 lines (114 loc) • 4.17 kB
JavaScript
;
Object.defineProperty(exports, '__esModule', { value: true });
var hooks = require('@react-vant-next/hooks');
var utils = require('@react-vant-next/utils');
var React = require('react');
function getDirection(x, y) {
if (x > y) {
return "horizontal";
}
if (y > x) {
return "vertical";
}
return "";
}
const INITIAL_STATE = {
startX: 0,
startY: 0,
deltaX: 0,
deltaY: 0,
offsetX: 0,
offsetY: 0,
_pointX: 0,
_pointY: 0,
/** 初始化偏移量计算渲染是否完成 */
ready: false,
direction: "",
};
function useFloatingTouch(props) {
const { boundary = true } = props;
const [state, update] = hooks.useSetState(INITIAL_STATE);
hooks.useIsomorphicLayoutEffect(() => {
if (!props.target)
return;
// Fill the initial offset state
const rect = props.target.getBoundingClientRect();
const { width, height } = rect;
const offset = Object.entries(props.offset).reduce((a, [k, v]) => {
let px = utils.unitToPx(v);
let axis = "deltaY";
if (k === "left")
px = window.innerWidth - px - width;
if (k === "top")
px = window.innerHeight - px - height;
if (k === "left" || k === "right")
axis = "deltaX";
// 右下角为坐标原点 取反值
a[axis] = -px;
return a;
}, {});
update(Object.assign({}, offset));
utils.raf(() => {
update({ ready: true });
});
}, [props.target]);
const getBound = React.useCallback(() => {
if (!props.target)
return {};
return props.target.getBoundingClientRect();
}, [props.target]);
const isVertical = React.useCallback(() => state.direction === "vertical", [state.direction]);
const isHorizontal = React.useCallback(() => state.direction === "horizontal", [state.direction]);
const reset = () => {
update(INITIAL_STATE);
};
const start = ((event) => {
const rect = getBound();
update(v => ({
startX: event.touches[0].clientX - v.deltaX,
startY: event.touches[0].clientY - v.deltaY,
_pointX: event.touches[0].clientX - rect.left,
_pointY: event.touches[0].clientY - rect.top,
}));
});
const move = ((event) => {
const touch = event.touches[0];
const rect = getBound();
update((value) => {
// Fix: Safari back will set clientX to negative number
const newState = Object.assign({}, value);
newState.deltaX = touch.clientX - newState.startX;
if (boundary && touch.clientX - newState._pointX <= 0)
newState.deltaX = -window.innerWidth + rect.width;
if (boundary
&& touch.clientX - newState._pointX >= window.innerWidth - rect.width) {
newState.deltaX = 0;
}
newState.deltaY = touch.clientY - newState.startY;
if (boundary && touch.clientY - newState._pointY <= 0)
newState.deltaY = -window.innerHeight + rect.height;
if (boundary
&& touch.clientY - newState._pointY >= window.innerHeight - rect.height) {
newState.deltaY = 0;
}
newState.offsetX = Math.abs(newState.deltaX);
newState.offsetY = Math.abs(newState.deltaY);
// lock direction when distance is greater than a certain value
const LOCK_DIRECTION_DISTANCE = 10;
if (!newState.direction
|| (newState.offsetX < LOCK_DIRECTION_DISTANCE
&& newState.offsetY < LOCK_DIRECTION_DISTANCE)) {
newState.direction = getDirection(newState.offsetX, newState.offsetY);
}
return newState;
});
});
return Object.assign(Object.assign({}, state), { update,
move,
start,
reset,
isVertical,
isHorizontal });
}
exports.default = useFloatingTouch;
//# sourceMappingURL=useFloatingTouch.js.map