UNPKG

react-native-zoom-toolkit

Version:

Smoothly zoom any image, video or component you want!

273 lines (270 loc) 10.7 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeReanimated = _interopRequireWildcard(require("react-native-reanimated")); var _reactNativeGestureHandler = require("react-native-gesture-handler"); var _clamp = require("../../commons/utils/clamp"); var _useVector = require("../../commons/hooks/useVector"); var _getMaxScale = require("../../commons/utils/getMaxScale"); var _useSizeVector = require("../../commons/hooks/useSizeVector"); var _usePanCommons = require("../../commons/hooks/usePanCommons"); var _pinchTransform = require("../../commons/utils/pinchTransform"); var _usePinchCommons = require("../../commons/hooks/usePinchCommons"); var _types = require("../../commons/types"); var _withResumableValidation = _interopRequireDefault(require("../../commons/hoc/withResumableValidation")); var _getPinchPanningStatus = require("../../commons/utils/getPinchPanningStatus"); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); } function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } const ResumableZoom = props => { const ref = props.reference; const { children, extendGestures = false, decay = true, tapsEnabled = true, panEnabled = true, pinchEnabled = true, minScale = 1, maxScale: userMaxScale = 6, panMode = _types.PanMode.CLAMP, scaleMode = _types.ScaleMode.BOUNCE, pinchCenteringMode = _types.PinchCenteringMode.CLAMP, allowPinchPanning: pinchPanning, onTap, onGestureActive, onGestureEnd, onSwipe, onPinchStart: onUserPinchStart, onPinchEnd: onUserPinchEnd, onPanStart: onUserPanStart, onPanEnd: onUserPanEnd, onOverPanning } = props; const allowPinchPanning = pinchPanning ?? (0, _getPinchPanningStatus.getPinchPanningStatus)(); const translate = (0, _useVector.useVector)(0, 0); const offset = (0, _useVector.useVector)(0, 0); const scale = (0, _reactNativeReanimated.useSharedValue)(minScale); const scaleOffset = (0, _reactNativeReanimated.useSharedValue)(minScale); const origin = (0, _useVector.useVector)(0, 0); const delta = (0, _useVector.useVector)(0, 0); const rootSize = (0, _useSizeVector.useSizeVector)(0, 0); const childSize = (0, _useSizeVector.useSizeVector)(0, 0); const extendedSize = (0, _useSizeVector.useSizeVector)(0, 0); const detectorTranslate = (0, _useVector.useVector)(0, 0); const detectorScale = (0, _reactNativeReanimated.useSharedValue)(minScale); const maxScale = (0, _reactNativeReanimated.useDerivedValue)(() => { if (typeof userMaxScale === 'object') { return (0, _getMaxScale.getMaxScale)({ width: childSize.width.value, height: childSize.height.value }, userMaxScale); } return userMaxScale; }, [userMaxScale, childSize]); (0, _reactNativeReanimated.useDerivedValue)(() => { extendedSize.width.value = extendGestures ? Math.max(rootSize.width.value, childSize.width.value) : childSize.width.value; extendedSize.height.value = extendGestures ? Math.max(rootSize.height.value, childSize.height.value) : childSize.height.value; }, [extendGestures, rootSize, childSize]); const boundsFn = scaleValue => { 'worklet'; const { width: cWidth, height: cHeight } = childSize; const { width: rWidth, height: rHeight } = rootSize; const boundX = Math.max(0, cWidth.value * scaleValue - rWidth.value) / 2; const boundY = Math.max(0, cHeight.value * scaleValue - rHeight.value) / 2; return { x: boundX, y: boundY }; }; const reset = (toX, toY, toScale, animate = true) => { 'worklet'; detectorTranslate.x.value = translate.x.value; detectorTranslate.y.value = translate.y.value; detectorScale.value = scale.value; translate.x.value = animate ? (0, _reactNativeReanimated.withTiming)(toX) : toX; translate.y.value = animate ? (0, _reactNativeReanimated.withTiming)(toY) : toY; scale.value = animate ? (0, _reactNativeReanimated.withTiming)(toScale) : toScale; detectorTranslate.x.value = animate ? (0, _reactNativeReanimated.withTiming)(toX) : toX; detectorTranslate.y.value = animate ? (0, _reactNativeReanimated.withTiming)(toY) : toY; detectorScale.value = animate ? (0, _reactNativeReanimated.withTiming)(toScale) : toScale; }; (0, _reactNativeReanimated.useDerivedValue)(() => { onGestureActive === null || onGestureActive === void 0 || onGestureActive({ width: childSize.width.value, height: childSize.height.value, translateX: translate.x.value, translateY: translate.y.value, scale: scale.value }); }, [translate, childSize, scale]); const { gesturesEnabled, onPinchStart, onPinchUpdate, onPinchEnd } = (0, _usePinchCommons.usePinchCommons)({ container: extendGestures ? extendedSize : childSize, detectorTranslate, detectorScale, translate, offset, origin, scale, scaleOffset, minScale, maxScale, delta, allowPinchPanning, scaleMode, pinchCenteringMode, boundFn: boundsFn, userCallbacks: { onGestureEnd, onPinchStart: onUserPinchStart, onPinchEnd: onUserPinchEnd } }); const { onPanStart, onPanChange, onPanEnd } = (0, _usePanCommons.usePanCommons)({ container: extendGestures ? extendedSize : childSize, detectorTranslate, translate, offset, scale, panMode, boundFn: boundsFn, decay, userCallbacks: { onSwipe, onGestureEnd, onPanStart: onUserPanStart, onPanEnd: onUserPanEnd, onOverPanning } }); const pinch = _reactNativeGestureHandler.Gesture.Pinch().enabled(pinchEnabled).onStart(onPinchStart).onUpdate(onPinchUpdate).onEnd(onPinchEnd); const pan = _reactNativeGestureHandler.Gesture.Pan().enabled(panEnabled && gesturesEnabled).maxPointers(1).onStart(onPanStart).onChange(onPanChange).onEnd(onPanEnd); const tap = _reactNativeGestureHandler.Gesture.Tap().enabled(tapsEnabled && gesturesEnabled).maxDuration(250).numberOfTaps(1).runOnJS(true).onEnd(e => onTap === null || onTap === void 0 ? void 0 : onTap(e)); const doubleTap = _reactNativeGestureHandler.Gesture.Tap().enabled(tapsEnabled && gesturesEnabled).maxDuration(250).numberOfTaps(2).onEnd(e => { const originX = e.x - extendedSize.width.value / 2; const originY = e.y - extendedSize.height.value / 2; const toScale = scale.value >= maxScale.value * 0.8 ? minScale : maxScale.value; const { x, y } = (0, _pinchTransform.pinchTransform)({ toScale: toScale, fromScale: scale.value, origin: { x: originX, y: originY }, delta: { x: 0, y: 0 }, offset: { x: translate.x.value, y: translate.y.value } }); const { x: boundX, y: boundY } = boundsFn(toScale); const toX = (0, _clamp.clamp)(x, -1 * boundX, boundX); const toY = (0, _clamp.clamp)(y, -1 * boundY, boundY); reset(toX, toY, toScale, true); }); const measureRoot = e => { rootSize.width.value = e.nativeEvent.layout.width; rootSize.height.value = e.nativeEvent.layout.height; }; const measureChild = e => { childSize.width.value = e.nativeEvent.layout.width; childSize.height.value = e.nativeEvent.layout.height; }; const childStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => ({ transform: [{ translateX: translate.x.value }, { translateY: translate.y.value }, { scale: scale.value }] }), [translate, scale]); const detectorStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { width: extendedSize.width.value, height: extendedSize.height.value, position: 'absolute', transform: [{ translateX: detectorTranslate.x.value }, { translateY: detectorTranslate.y.value }, { scale: detectorScale.value }] }; }, [childSize, rootSize, detectorTranslate, detectorScale]); const requestState = () => { return { width: childSize.width.value, height: childSize.height.value, translateX: translate.x.value, translateY: translate.y.value, scale: scale.value }; }; const assignState = (state, animate = true) => { const toScale = (0, _clamp.clamp)(state.scale, minScale, maxScale.value); const { x: boundX, y: boundY } = boundsFn(toScale); const toX = (0, _clamp.clamp)(state.translateX, -1 * boundX, boundX); const toY = (0, _clamp.clamp)(state.translateY, -1 * boundY, boundY); reset(toX, toY, toScale, animate); }; (0, _react.useImperativeHandle)(ref, () => ({ reset: animate => reset(0, 0, minScale, animate), requestState: requestState, assignState: assignState })); const composedTap = _reactNativeGestureHandler.Gesture.Exclusive(doubleTap, tap); const composedGesture = _reactNativeGestureHandler.Gesture.Race(pinch, pan, composedTap); return /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.GestureHandlerRootView, { style: styles.root, onLayout: measureRoot }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: childStyle, onLayout: measureChild }, children), /*#__PURE__*/_react.default.createElement(_reactNativeGestureHandler.GestureDetector, { gesture: composedGesture }, /*#__PURE__*/_react.default.createElement(_reactNativeReanimated.default.View, { style: detectorStyle }))); }; const styles = _reactNative.StyleSheet.create({ root: { flex: 1, justifyContent: 'center', alignItems: 'center' } }); var _default = exports.default = (0, _withResumableValidation.default)(ResumableZoom); //# sourceMappingURL=ResumableZoom.js.map