UNPKG

react-native-gallery-preview

Version:

<div> <img align="right" height="720" src="example.gif"> </div>

315 lines (308 loc) 15 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.GestureItemComponent = 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 _constants = require("../../constants"); var _clamp = require("../../utils/clamp"); var _useVector = require("../../utils/useVector"); var _jsxRuntime = require("react/jsx-runtime"); function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } // import { DebugView } from "./DebugView/DebugView"; const GestureItemComponent = exports.GestureItemComponent = /*#__PURE__*/(0, _react.memo)(({ children, index, currentIndex, isFirst, isLast, rootTranslateX, opacity, dataLength, width, height, gap, onClose, setIsFocused, isFocused, maxScale, springConfig, doubleTabEnabled, swipeToCloseEnabled, pinchEnabled, rtl, contentCenterX, contentCenterY, contentContainerSize }) => { const initRootTranslateX = (0, _reactNativeReanimated.useSharedValue)(0); const offset = (0, _useVector.useVector)(0, 0); const translation = (0, _useVector.useVector)(0, 0); const savedTranslation = (0, _useVector.useVector)(0, 0); const initialFocal = (0, _useVector.useVector)(0, 0); const scale = (0, _reactNativeReanimated.useSharedValue)(1); const savedScale = (0, _reactNativeReanimated.useSharedValue)(1); const isPanningOut = (0, _reactNativeReanimated.useSharedValue)(false); const shouldClose = (0, _reactNativeReanimated.useSharedValue)(false); const animationContentContainerStyle = (0, _reactNativeReanimated.useAnimatedStyle)(() => { return { transform: [{ translateX: offset.x.value + translation.x.value }, { translateY: offset.y.value + translation.y.value }, { scale: scale.value }] }; }); const onStartInteraction = withUnFocus => { "worklet"; offset.x.value = offset.x.value + translation.x.value; offset.y.value = offset.y.value + translation.y.value; translation.x.value = 0; translation.y.value = 0; if (withUnFocus) { (0, _reactNativeReanimated.runOnJS)(setIsFocused)(false); } }; const getImagePositionX = (0, _react.useCallback)(i => { "worklet"; if (rtl) { return [(width + gap) * i, width * (i + 1)]; } return [-(width + gap) * i, -width * (i + 1)]; }, [gap, width, rtl]); const getScaledEdgesX = scaleValue => { "worklet"; const _scale = scaleValue !== undefined ? scaleValue : scale.value; const scaledWith = _scale * contentContainerSize.width; const xPoint = Math.abs((scaledWith - width) / 2); return [-xPoint, xPoint]; }; const getScaledEdgesY = scaleValue => { "worklet"; const _scale = scaleValue !== undefined ? scaleValue : scale.value; const scaledHeight = _scale * contentContainerSize.height; const yPoint = Math.abs((scaledHeight - height) / 2); return [-yPoint, yPoint]; }; const reset = () => { "worklet"; translation.x.value = scale.value > 1 ? (0, _reactNativeReanimated.withTiming)(0, { duration: _constants.DURATION }) : (0, _reactNativeReanimated.withSpring)(0, springConfig); translation.y.value = scale.value > 1 ? (0, _reactNativeReanimated.withTiming)(0, { duration: _constants.DURATION }) : (0, _reactNativeReanimated.withSpring)(0, springConfig); offset.x.value = scale.value > 1 ? (0, _reactNativeReanimated.withTiming)(0, { duration: _constants.DURATION }) : (0, _reactNativeReanimated.withSpring)(0, springConfig); offset.y.value = scale.value > 1 ? (0, _reactNativeReanimated.withTiming)(0, { duration: _constants.DURATION }) : (0, _reactNativeReanimated.withSpring)(0, springConfig); opacity.value = (0, _reactNativeReanimated.withTiming)(1, { duration: _constants.DURATION }); scale.value = (0, _reactNativeReanimated.withTiming)(1, { duration: _constants.DURATION }); rootTranslateX.value = (0, _reactNativeReanimated.withSpring)(getImagePositionX(index)[0], springConfig); }; const pinchGesture = _reactNativeGestureHandler.Gesture.Pinch().enabled(pinchEnabled).onStart(event => { onStartInteraction(true); initialFocal.x.value = event.focalX - (width / 2 + offset.x.value); initialFocal.y.value = event.focalY - (height / 2 + offset.y.value); savedScale.value = scale.value; }).onUpdate(event => { if (event.numberOfPointers !== 2) return; const deltaX = event.focalX - (width / 2 + offset.x.value); const deltaY = event.focalY - (height / 2 + offset.y.value); translation.x.value = deltaX + -1 * scale.value / savedScale.value * initialFocal.x.value; translation.y.value = deltaY + -1 * scale.value / savedScale.value * initialFocal.y.value; scale.value = (0, _clamp.withRubberClamp)(savedScale.value * event.scale, 0.45, maxScale, _constants.MIN_SCALE, maxScale); }).onEnd(() => { if (scale.value <= 1) { reset(); } else { if (scale.value > maxScale) { const diffX = -1 * maxScale / savedScale.value * initialFocal.x.value - -1 * scale.value / savedScale.value * initialFocal.x.value; const diffY = -1 * maxScale / savedScale.value * initialFocal.y.value - -1 * scale.value / savedScale.value * initialFocal.y.value; translation.x.value = (0, _reactNativeReanimated.withTiming)(translation.x.value + diffX, { duration: _constants.DURATION }); translation.y.value = (0, _reactNativeReanimated.withTiming)(translation.y.value + diffY, { duration: _constants.DURATION }); scale.value = (0, _reactNativeReanimated.withTiming)(maxScale, { duration: _constants.DURATION }); } else { const edgesX = getScaledEdgesX(); const edgesY = getScaledEdgesY(); if (offset.x.value + translation.x.value > edgesX[1]) { translation.x.value = (0, _reactNativeReanimated.withSpring)(edgesX[1] - offset.x.value, springConfig); } else if (offset.x.value + translation.x.value < edgesX[0]) { translation.x.value = (0, _reactNativeReanimated.withSpring)(edgesX[0] - offset.x.value, springConfig); } const currHeight = contentContainerSize.height * scale.value; if (currHeight > height) { if (offset.y.value + translation.y.value > edgesY[1]) { translation.y.value = (0, _reactNativeReanimated.withSpring)(edgesY[1] - offset.y.value, springConfig); } else if (offset.y.value + translation.y.value < edgesY[0]) { translation.y.value = (0, _reactNativeReanimated.withSpring)(edgesY[0] - offset.y.value, springConfig); } } else { translation.y.value = (0, _reactNativeReanimated.withSpring)(0, springConfig); offset.y.value = (0, _reactNativeReanimated.withSpring)(0, springConfig); } } } }); const panGesture = _reactNativeGestureHandler.Gesture.Pan().minDistance(10).maxPointers(1).onStart(event => { onStartInteraction(); if (scale.value === 1 && event.velocityY > event.velocityX) { rootTranslateX.value = getImagePositionX(currentIndex.value)[0]; } initRootTranslateX.value = rootTranslateX.value; savedTranslation.x.value = translation.x.value; savedTranslation.y.value = translation.y.value; isPanningOut.value = false; shouldClose.value = false; }).onUpdate(event => { const { translationX, translationY, velocityY, velocityX } = event; const edgesX = getScaledEdgesX(); const edgesY = getScaledEdgesY(); isPanningOut.value = !isPanningOut.value ? swipeToCloseEnabled && scale.value === 1 && getImagePositionX(index)[0] === rootTranslateX.value && (velocityY > 0 && velocityY > Math.abs(velocityX) || translationY > Math.abs(translationX)) : isPanningOut.value; if (scale.value === 1 && !isPanningOut.value) { if (rtl) { rootTranslateX.value = (0, _clamp.withRubberClamp)(initRootTranslateX.value + translationX, { dir0: isLast ? 0.55 : 1.15, dir1: isFirst ? 0.55 : 1.15 }, width, 0, getImagePositionX(dataLength - 1)[0]); } else { rootTranslateX.value = (0, _clamp.withRubberClamp)(initRootTranslateX.value + translationX, { dir0: isFirst ? 0.55 : 1.15, dir1: isLast ? 0.55 : 1.15 }, width, getImagePositionX(dataLength - 1)[0], 0); } return; } else { translation.x.value = (0, _clamp.withRubberClamp)(savedTranslation.x.value + translationX, 0.55, contentContainerSize.width * scale.value, edgesX[0], edgesX[1]); } if (isPanningOut.value) { if (translation.y.value === 0 && Math.abs(velocityY) > Math.abs(velocityX) && velocityY > height) { shouldClose.value = true; (0, _reactNativeReanimated.runOnJS)(onClose)(); return; } translation.y.value = (0, _clamp.withRubberClamp)(savedTranslation.y.value + translationY, { dir0: 1, dir1: 0.55 }, contentContainerSize.height * scale.value, 0, edgesY[1]); opacity.value = (0, _reactNativeReanimated.interpolate)(translation.y.value, [0, height / 2], [1, 0]); scale.value = (0, _reactNativeReanimated.interpolate)(translation.y.value, [0, height / 2], [1, 0.66]); shouldClose.value = velocityY >= 0 && translation.y.value + velocityY * 0.3 > contentContainerSize.height / 10; } else { translation.y.value = (0, _clamp.withRubberClamp)(savedTranslation.y.value + translationY, 0.55, contentContainerSize.height * scale.value, edgesY[0], edgesY[1]); } }).onEnd(event => { if (shouldClose.value) { (0, _reactNativeReanimated.runOnJS)(onClose)(); return; } else if (isPanningOut.value) { reset(); return; } const currentImagePositionX = getImagePositionX(index); const { velocityX, translationX } = event; const edgesX = getScaledEdgesX(); const edgesY = getScaledEdgesY(); if (scale.value === 1) { const needToTransX = Math.abs(getImagePositionX(1)[0] / 2); if (rtl && (isFirst && translationX < 0 || isLast && translationX > 0) || !rtl && (isFirst && translationX > 0 || isLast && translationX < 0)) { rootTranslateX.value = (0, _reactNativeReanimated.withSpring)(currentImagePositionX[0], springConfig); } else if (Math.abs(velocityX) >= needToTransX || Math.abs(translationX) >= needToTransX) { const newIndex = rtl ? !isFirst && velocityX <= 0 && translationX < 0 ? index - 1 : !isLast && velocityX >= 0 && translationX > 0 ? index + 1 : index : !isFirst && velocityX >= 0 && translationX > 0 ? index - 1 : !isLast && velocityX <= 0 && translationX < 0 ? index + 1 : index; const newPosition = getImagePositionX(newIndex); rootTranslateX.value = (0, _reactNativeReanimated.withSpring)(newPosition[0], springConfig); currentIndex.value = newIndex; } else { rootTranslateX.value = (0, _reactNativeReanimated.withSpring)(currentImagePositionX[0], springConfig); } } else { if (translation.x.value + offset.x.value > edgesX[1] || translation.x.value + offset.x.value < edgesX[0]) { translation.x.value = (0, _reactNativeReanimated.withSpring)((0, _reactNativeReanimated.clamp)(translation.x.value, edgesX[0] - offset.x.value, edgesX[1] - offset.x.value), springConfig); } if (translation.y.value + offset.y.value > edgesY[1] || translation.y.value + offset.y.value < edgesY[0]) { translation.y.value = (0, _reactNativeReanimated.withSpring)((0, _reactNativeReanimated.clamp)(translation.y.value, edgesY[0] - offset.y.value, edgesY[1] - offset.y.value), springConfig); } } }); const doubleTap = _reactNativeGestureHandler.Gesture.Tap().enabled(doubleTabEnabled).numberOfTaps(2).onStart(() => { onStartInteraction(true); }).onEnd(event => { if (event.numberOfPointers !== 1) { return; } if (scale.value > 1) { reset(); } else { const zoomScale = height > width ? Math.min(contentContainerSize.width > contentContainerSize.height ? height / contentContainerSize.height * 1.1 : 2.5, maxScale) : Math.min(contentContainerSize.height > contentContainerSize.width ? width / contentContainerSize.width * 1.1 : 2.5, maxScale); const edgesX = getScaledEdgesX(zoomScale); const edgesY = getScaledEdgesY(zoomScale); translation.x.value = (0, _reactNativeReanimated.withTiming)((0, _reactNativeReanimated.clamp)((contentCenterX - event.x) * (zoomScale - 1), edgesX[0], edgesX[1]), { duration: _constants.DURATION }); translation.y.value = (0, _reactNativeReanimated.withTiming)((0, _reactNativeReanimated.clamp)((contentCenterY - event.y) * (zoomScale - 1), edgesY[0], edgesY[1]), { duration: _constants.DURATION }); scale.value = (0, _reactNativeReanimated.withTiming)(zoomScale, { duration: _constants.DURATION }); savedScale.value = zoomScale; } }); const tap = _reactNativeGestureHandler.Gesture.Tap().numberOfTaps(1).requireExternalGestureToFail(doubleTap).onEnd(() => { (0, _reactNativeReanimated.runOnJS)(setIsFocused)(!isFocused); }); const gestures = _reactNativeGestureHandler.Gesture.Exclusive(_reactNativeGestureHandler.Gesture.Race(panGesture, pinchGesture), tap); return /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.wrapper, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, { gesture: gestures, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.container, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, { style: animationContentContainerStyle, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeGestureHandler.GestureDetector, { gesture: doubleTap, children: children }) }) }) }) }); }); const styles = _reactNative.StyleSheet.create({ wrapper: { flex: 1 }, container: { flex: 1, justifyContent: "center", alignItems: "center", overflow: "hidden" } }); //# sourceMappingURL=GestureItemComponent.js.map