@bytedance/mona-client-web
Version:
web for mona
269 lines • 11.8 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
import React, { useRef, useEffect, useState, useCallback } from 'react';
import { formatTouchEvent, genEvent } from '../utils';
import styles from './index.module.less';
import { useHandlers } from '../hooks';
var getDistance = function (start, stop) {
return Math.hypot(stop.x - start.x, stop.y - start.y);
};
var checkPosi = function (value, wrapperInfo, itemInfo, outOfBounds) {
var x = value.x, y = value.y;
var wrapperWidth = wrapperInfo.wrapperWidth, wrapperHeight = wrapperInfo.wrapperHeight;
var itemWidth = itemInfo.itemWidth, itemHeight = itemInfo.itemHeight;
var _a = [true, true], overflowX = _a[0], overflowY = _a[1];
var xLimit = wrapperWidth - itemWidth;
var yLimit = wrapperHeight - itemHeight;
var _b = [0, xLimit], xMin = _b[0], xMax = _b[1];
var _c = [0, yLimit], yMin = _c[0], yMax = _c[1];
if (outOfBounds) {
var xOverflowLimit = (itemWidth / 2) * 0.8;
var yOverflowLimit = (itemHeight / 2) * 0.8;
xMin -= xOverflowLimit;
xMax += xOverflowLimit;
yMin -= yOverflowLimit;
yMax += yOverflowLimit;
}
if (x < xMin) {
x = xMin;
}
else if (x > xMax) {
x = xMax;
}
if (x >= 0 && x <= xLimit) {
overflowX = false;
}
if (y < yMin) {
y = yMin;
}
else if (y > yMax) {
y = yMax;
}
if (y >= 0 && y <= yLimit) {
overflowY = false;
}
return {
data: { x: x, y: y },
overflow: overflowY || overflowX,
};
};
var MovableView = function (props) {
var
// scale,
_a = props.scaleValue,
// scale,
scaleValue = _a === void 0 ? 1 : _a, _b = props.scaleMax, scaleMax = _b === void 0 ? 10 : _b, _c = props.scaleMin, scaleMin = _c === void 0 ? 0.5 : _c, children = props.children, disabled = props.disabled, _d = props.x, x = _d === void 0 ? 0 : _d, _e = props.y, y = _e === void 0 ? 0 : _e,
// onScale,
_f = props.damping,
// onScale,
damping = _f === void 0 ? 20 : _f, _g = props.friction, friction = _g === void 0 ? 2 : _g,
//@ts-ignore
wrapperWidth = props.wrapperWidth,
//@ts-ignore
wrapperHeight = props.wrapperHeight,
//@ts-ignore
wrapperRef = props.wrapperRef,
//@ts-ignore
scaleArea = props.scaleArea, className = props.className, onHtouchMove = props.onHtouchMove, onVtouchMove = props.onVtouchMove, inertia = props.inertia, outOfBounds = props.outOfBounds, scale = props.scale, animation = props.animation, restProps = __rest(props, ["scaleValue", "scaleMax", "scaleMin", "children", "disabled", "x", "y", "damping", "friction", "wrapperWidth", "wrapperHeight", "wrapperRef", "scaleArea", "className", "onHtouchMove", "onVtouchMove", "inertia", "outOfBounds", "scale", "animation"]);
// const ref = useRef<HTMLDivElement>(null);
var domRef = useRef(null);
var disRef = useRef({ distX: 0, distY: 0 });
var propsRef = useRef(props);
var stateRef = useRef({});
var _h = useState({ x: 0, y: 0 }), _j = _h[0], innerX = _j.x, innerY = _j.y, setPosition = _h[1];
var _k = useState(false), executing = _k[0], setExecuting = _k[1];
var _l = useState(scaleValue), innerScale = _l[0], setScale = _l[1];
var _m = useHandlers(restProps), handleClassName = _m.handleClassName, handlerProps = __rest(_m, ["handleClassName"]);
useEffect(function () {
var sValue = scaleValue < scaleMax ? (scaleValue > scaleMin ? scaleValue : scaleMin) : scaleMax;
setScale(sValue);
}, [scaleValue, scaleMax, scaleMin]);
propsRef.current = props;
stateRef.current = {
executing: executing,
};
var setPositionWithCheck = useCallback(function (posi, outOfBounds, e) {
outOfBounds = outOfBounds === undefined ? propsRef.current.outOfBounds : outOfBounds;
var check = function (posi) {
var _a, _b, _c;
var _d = (_a = domRef.current.getBoundingClientRect()) !== null && _a !== void 0 ? _a : {}, realWidth = _d.width, realHeight = _d.height;
var _e = checkPosi(posi, { wrapperWidth: wrapperWidth, wrapperHeight: wrapperHeight }, {
// 获取scale之后的宽高
itemHeight: realHeight,
itemWidth: realWidth,
}, !!outOfBounds), data = _e.data, overflow = _e.overflow;
var formatEvent;
if (e) {
formatEvent = formatTouchEvent({ event: e, type: 'change' });
formatEvent.detail = __assign({}, data);
if (overflow) {
formatEvent.detail.source = 'touch-out-of-bounds';
}
else {
formatEvent.detail.source = 'touch';
}
}
else {
formatEvent = genEvent({ detail: {}, type: 'change' });
formatEvent.detail = __assign({}, data);
formatEvent.detail.source = '';
}
(_c = (_b = propsRef.current).onChange) === null || _c === void 0 ? void 0 : _c.call(_b, formatEvent);
return { data: data, overflow: overflow };
};
if (typeof posi === 'function') {
setPosition(function (pre) { return check(posi(pre)).data; });
}
else {
setPosition(check(posi).data);
}
}, [wrapperWidth, wrapperHeight]);
useEffect(function () {
setExecuting(true);
setPositionWithCheck({ x: +x, y: +y }, false);
}, [x, y, setPositionWithCheck]);
var handleTouchStart = useCallback(function (e) {
setExecuting(false);
var _a = e.targetTouches[0], clientX = _a.clientX, clientY = _a.clientY;
var posInfo = domRef.current.getBoundingClientRect();
disRef.current.distX = clientX - posInfo.left;
disRef.current.distY = clientY - posInfo.top;
}, []);
var handleScale = useCallback(function (e) {
var _a = e.targetTouches[0], clientX = _a.clientX, clientY = _a.clientY;
var _b = disRef.current, distX = _b.distX, distY = _b.distY;
var L = clientX - distX, T = clientY - distY;
if (!propsRef.current.scale) {
return;
}
var touches = e.targetTouches;
var events = touches[0];
var events2 = touches[1];
var zoom = getDistance({
x: events.pageX,
y: events.pageY,
}, {
x: events2.pageX,
y: events2.pageY,
});
setScale(function (preScale) {
var _a, _b;
var _c = propsRef.current, scaleMin = _c.scaleMin, scaleMax = _c.scaleMax;
var newScaleValue = preScale * zoom;
var res = newScaleValue < scaleMax ? (newScaleValue > scaleMin ? newScaleValue : scaleMin) : scaleMax;
var formatEvent = formatTouchEvent({ event: e, type: 'change' });
formatEvent.detail = {
x: L,
y: T,
scale: res,
};
(_b = (_a = propsRef.current).onScale) === null || _b === void 0 ? void 0 : _b.call(_a, formatEvent);
return res;
});
}, []);
var handleTouchMove = useCallback(function (e) {
var tLength = e.targetTouches.length;
var _a = e.targetTouches[0], clientX = _a.clientX, clientY = _a.clientY;
var _b = disRef.current, distX = _b.distX, distY = _b.distY;
var L = clientX - distX, T = clientY - distY;
if (tLength === 1) {
var direction = propsRef.current.direction;
if (direction === 'horizontal') {
setPositionWithCheck(function (pre) { return ({ x: L, y: pre.y }); }, undefined, e);
}
else if (direction === 'vertical') {
setPositionWithCheck(function (pre) { return ({ x: pre.x, y: T }); }, undefined, e);
}
else if (direction === 'all') {
setPositionWithCheck({ x: L, y: T }, undefined, e);
}
else {
return;
}
}
else if (tLength === 2) {
!scaleArea && handleScale(e);
}
}, [setPositionWithCheck, handleScale, scaleArea]);
var handleTouchEnd = useCallback(function (e) {
setPosition(function (_a) {
var _b, _c, _d;
var x = _a.x, y = _a.y;
var _e = propsRef.current, wrapperWidth = _e.wrapperWidth, wrapperHeight = _e.wrapperHeight;
var _f = (_b = domRef.current.getBoundingClientRect()) !== null && _b !== void 0 ? _b : {}, realWidth = _f.width, realHeight = _f.height;
var data = checkPosi({ x: x, y: y }, { wrapperWidth: wrapperWidth, wrapperHeight: wrapperHeight }, {
itemHeight: realHeight,
itemWidth: realWidth,
}, false).data;
var formatEvent;
formatEvent = formatTouchEvent({ event: e, type: 'change' });
formatEvent.detail = __assign({}, data);
formatEvent.detail.source = 'out-of-bounds';
if (data.x !== x || data.y !== y) {
(_d = (_c = propsRef.current).onChange) === null || _d === void 0 ? void 0 : _d.call(_c, formatEvent);
setExecuting(true);
}
return data;
});
}, [setPositionWithCheck]);
var animationTime = "".concat(4 / friction / damping, "s");
var transitionStyle = executing
? {
transition: "scale ".concat(animationTime, ", transform ").concat(animationTime),
}
: { transition: "scale ".concat(animationTime) };
useEffect(function () {
var wrapperDom = wrapperRef === null || wrapperRef === void 0 ? void 0 : wrapperRef.current;
if (wrapperDom && scaleArea) {
wrapperDom.addEventListener('touchmove', handleScale);
}
return function () {
scaleArea && wrapperDom.removeEventListener('touchmove', handleScale);
};
}, [handleScale, scaleArea, wrapperRef]);
return (
//@ts-ignore
React.createElement("span", __assign({ ref: domRef }, handlerProps, {
//@ts-ignore
onTransitionEnd: function () { return setExecuting(false); },
//@ts-ignore
onTouchStart: disabled ? undefined : handleTouchStart,
//@ts-ignore
onTouchMove: disabled ? undefined : handleTouchMove,
//@ts-ignore
onTouchEnd: disabled ? undefined : handleTouchEnd, style: __assign({ transform: "translate(".concat(innerX, "px, ").concat(innerY, "px) scale(").concat(innerScale, ")") }, transitionStyle), className: handleClassName([className, styles.touch]) }), children));
};
export default MovableView;
MovableView.defaultProps = {
direction: 'none',
inertia: false,
outOfBounds: false,
damping: 20,
friction: 2,
disabled: false,
scale: false,
scaleMin: 0.5,
scaleMax: 10,
animation: true,
};
//# sourceMappingURL=index.js.map