UNPKG

@gdjiami/hooks

Version:

react hooks for mygzb.com

163 lines (162 loc) 5.87 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var tslib_1 = require("tslib"); var react_1 = require("react"); var useGesture_1 = tslib_1.__importDefault(require("./useGesture")); var useRefProps_1 = tslib_1.__importDefault(require("./useRefProps")); var useRefState_1 = tslib_1.__importDefault(require("./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注入可拖拽行为 */ function useDraggable(options) { if (options === void 0) { options = {}; } var _a = tslib_1.__read(react_1.useState(false), 2), dragging = _a[0], setDragging = _a[1]; var _b = tslib_1.__read(useRefState_1.default(options.defaultTranslate || DEFAULT_TRANSLATE), 3), offset = _b[0], setOffset = _b[1], offsetRef = _b[2]; var optionsRef = useRefProps_1.default(options); var x = offset.x, y = offset.y; var el = useGesture_1.default({ onDown: function (info) { if (optionsRef.current.onDown && optionsRef.current.onDown(info) === false) { return false; } setDragging(true); return; }, onMove: function (info) { var axis = optionsRef.current.axis; var _a = restrictInBounds({ x: info.deltaX, y: info.deltaY }, info.target, optionsRef.current.bounds || (optionsRef.current.edge ? 'body' : undefined)), deltaX = _a.x, deltaY = _a.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 (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, }).ref; var resetOffset = react_1.useCallback(function () { var _a = restrictInBounds(optionsRef.current.defaultTranslate || DEFAULT_TRANSLATE, el.current, optionsRef.current.bounds || (optionsRef.current.edge ? 'body' : undefined)), x = _a.x, y = _a.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); }, []); react_1.useEffect(function () { resetOffset(); }, []); react_1.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 }; } exports.default = useDraggable;