@gdjiami/hooks
Version:
react hooks for mygzb.com
219 lines (183 loc) • 5.27 kB
JavaScript
import { useEffect, useState, useCallback } from 'react';
import useGesture from './useGesture';
import useRefProps from './useRefProps';
import useRefState from './useRefState';
/**
* 获取
* @param el
*/
function getElementBounds(el) {
var bounds = el.getBoundingClientRect();
return {
x: bounds.left,
y: bounds.top,
width: bounds.width,
height: bounds.height
};
}
/**
* 限定在指定区域内
*
* @param offset
* @param el
* @param bounds
*/
function restrictInBounds(offset, el, bounds) {
if (bounds == null) {
return offset;
}
var elRect = getElementBounds(el);
var boundRect;
if (typeof bounds === 'string') {
var boundEl = bounds === 'parent' ? el.parentElement : document.querySelector(bounds);
if (boundEl == null || !(boundEl instanceof HTMLElement)) {
throw Error('Bounds selector "' + bounds + '" could not find an element.');
}
boundRect = getElementBounds(boundEl);
} else {
boundRect = bounds;
}
var coordAfterDrag = {
x: elRect.x + offset.x,
y: elRect.y + offset.y
};
var right = coordAfterDrag.x + elRect.width;
var bottom = coordAfterDrag.y + elRect.height;
var boundsRight = boundRect.x + boundRect.width;
var boundsBottom = boundRect.y + boundRect.height;
var x = coordAfterDrag.x;
var y = coordAfterDrag.y;
if (right > boundsRight) {
x -= right - boundsRight;
}
if (bottom > boundsBottom) {
y -= bottom - boundsBottom;
}
x = Math.max(x, boundRect.x);
y = Math.max(y, boundRect.y);
return {
x: x - elRect.x,
y: y - elRect.y
};
}
/**
* 停靠边缘
*/
function berthEdge(offset, el, bounds, padding) {
if (bounds === void 0) {
bounds = 'body';
}
if (padding === void 0) {
padding = 0;
}
var elRect = getElementBounds(el);
var boundRect;
if (typeof bounds === 'string') {
var boundEl = bounds === 'parent' ? el.parentElement : document.querySelector(bounds);
if (boundEl == null || !(boundEl instanceof HTMLElement)) {
throw Error('Bounds selector "' + bounds + '" could not find an element.');
}
boundRect = getElementBounds(boundEl);
} else {
boundRect = bounds;
}
var x = elRect.x - boundRect.x > boundRect.width / 2 ? boundRect.width - (elRect.width + padding) // right berth
: padding;
return {
x: x,
y: offset.y
};
}
var DEFAULT_TRANSLATE = {
x: 0,
y: 0
};
/**
* 给指定element注入可拖拽行为
*/
export default function useDraggable(options) {
if (options === void 0) {
options = {};
}
var _useState = useState(false),
dragging = _useState[0],
setDragging = _useState[1];
var _useRefState = useRefState(options.defaultTranslate || DEFAULT_TRANSLATE),
offset = _useRefState[0],
setOffset = _useRefState[1],
offsetRef = _useRefState[2];
var optionsRef = useRefProps(options);
var x = offset.x,
y = offset.y;
var _useGesture = useGesture({
onDown: function onDown(info) {
if (optionsRef.current.onDown && optionsRef.current.onDown(info) === false) {
return false;
}
setDragging(true);
return;
},
onMove: function onMove(info) {
var axis = optionsRef.current.axis;
var _restrictInBounds = restrictInBounds({
x: info.deltaX,
y: info.deltaY
}, info.target, optionsRef.current.bounds || (optionsRef.current.edge ? 'body' : undefined)),
deltaX = _restrictInBounds.x,
deltaY = _restrictInBounds.y;
var offset = offsetRef.current;
var newOffset = {
x: axis === 'y' ? offset.x : deltaX + offset.x,
y: axis === 'x' ? offset.y : deltaY + offset.y
};
if (optionsRef.current.onMove) {
optionsRef.current.onMove(info, offset);
}
setOffset(newOffset);
return;
},
onUp: function onUp(info) {
setDragging(false);
var offset = offsetRef.current;
if (optionsRef.current.edge) {
offset = berthEdge(offset, info.target, optionsRef.current.bounds, optionsRef.current.edgePadding);
requestAnimationFrame(function () {
setOffset(offset);
});
}
if (optionsRef.current.onUp) {
optionsRef.current.onUp(info, offset);
}
},
ref: options.ref
}),
el = _useGesture.ref;
var resetOffset = useCallback(function () {
var _restrictInBounds2 = restrictInBounds(optionsRef.current.defaultTranslate || DEFAULT_TRANSLATE, el.current, optionsRef.current.bounds || (optionsRef.current.edge ? 'body' : undefined)),
x = _restrictInBounds2.x,
y = _restrictInBounds2.y;
var offset = offsetRef.current;
offset = {
x: x + offset.x,
y: y + offset.y
};
if (optionsRef.current.edge) {
offset = berthEdge(offset, el.current, optionsRef.current.bounds, optionsRef.current.edgePadding);
}
setOffset(offset);
}, []);
useEffect(function () {
resetOffset();
}, []);
useEffect(function () {
if (!optionsRef.current.disableTransform) {
el.current.style.transform = "translate3d(" + x + "px, " + y + "px, 0)";
}
}, [x, y]);
return {
ref: el,
dragging: dragging,
translate: offset,
resetOffset: resetOffset
};
}