diff --git a/lib/commonjs/ReactNativeZoomableView.js b/lib/commonjs/ReactNativeZoomableView.js index 7c0ab63..9687fd8 100644 --- a/lib/commonjs/ReactNativeZoomableView.js +++ b/lib/commonjs/ReactNativeZoomableView.js @@ -34,10 +34,10 @@ function _extends() { _extends = Object.assign || function (target) { for (var i function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } const initialState = { - originalWidth: null, - originalHeight: null, - originalPageX: null, - originalPageY: null, + originalWidth: 0, + originalHeight: 0, + originalPageX: 0, + originalPageY: 0, pinSize: { width: 0, height: 0 @@ -305,7 +305,7 @@ class ReactNativeZoomableView extends _react.Component { delete this.doubleTapFirstTap; this._handleDoubleTap(e); - } else if (this.state.originalPageX && this.state.originalPageY) { + } else { this.doubleTapFirstTapReleaseTimestamp = now; this.doubleTapFirstTap = { id: now.toString(), @@ -344,7 +344,7 @@ class ReactNativeZoomableView extends _react.Component { } }); - _defineProperty(this, "moveStaticPinTo", position => { + _defineProperty(this, "moveStaticPinTo", (position, duration) => { const { originalWidth, originalHeight @@ -362,10 +362,22 @@ class ReactNativeZoomableView extends _react.Component { const pinY = staticPinPosition.y - originalHeight / 2; this.offsetX = contentWidth / 2 - position.x + pinX / this.zoomLevel; this.offsetY = contentHeight / 2 - position.y + pinY / this.zoomLevel; - this.panAnim.setValue({ - x: this.offsetX, - y: this.offsetY - }); + + if (duration) { + _reactNative.Animated.timing(this.panAnim, { + toValue: { + x: this.offsetX, + y: this.offsetY + }, + useNativeDriver: true, + duration + }).start(); + } else { + this.panAnim.setValue({ + x: this.offsetX, + y: this.offsetY + }); + } }); _defineProperty(this, "_staticPinPosition", () => { @@ -684,8 +696,6 @@ class ReactNativeZoomableView extends _react.Component { const gestureCenterPoint = (0, _helper.calcGestureCenterPoint)(e, gestureState); if (!gestureCenterPoint) return; - if (this.state.originalPageX == null) return; - if (this.state.originalPageY == null) return; let zoomCenter = { x: gestureCenterPoint.x - this.state.originalPageX, y: gestureCenterPoint.y - this.state.originalPageY @@ -747,8 +757,6 @@ class ReactNativeZoomableView extends _react.Component { originalPageY, originalPageX } = this.state; - if (originalPageX == null) return; - if (originalPageY == null) return; this.setState({ debugPoints: [{ x: touches[0].pageX - originalPageX, @@ -901,9 +909,7 @@ class ReactNativeZoomableView extends _react.Component { const { originalPageX, originalPageY - } = this.state; - if (originalPageX == null) return; - if (originalPageY == null) return; // define new zoom position coordinates + } = this.state; // define new zoom position coordinates const zoomPositionCoordinates = { x: e.nativeEvent.pageX - originalPageX, @@ -968,8 +974,6 @@ class ReactNativeZoomableView extends _react.Component { var _this$props$onZoomBef, _this$props17, _this$props$onZoomAft2, _this$props18; if (!this.props.zoomEnabled) return; - if (this.state.originalWidth == null) return; - if (this.state.originalHeight == null) return; (_this$props$onZoomBef = (_this$props17 = this.props).onZoomBefore) === null || _this$props$onZoomBef === void 0 ? void 0 : _this$props$onZoomBef.call(_this$props17, null, null, this._getZoomableViewEventObject()); // == Perform Zoom Animation == // Calculates panAnim values based on changes in zoomAnim. @@ -981,8 +985,6 @@ class ReactNativeZoomableView extends _react.Component { const listenerId = this.zoomAnim.addListener(({ value: newScale }) => { - if (this.state.originalWidth == null) return; - if (this.state.originalHeight == null) return; this.panAnim.setValue({ x: (0, _helper.calcNewScaledOffsetForZoomCentering)(this.offsetX, this.state.originalWidth, prevScale, newScale, x), y: (0, _helper.calcNewScaledOffsetForZoomCentering)(this.offsetY, this.state.originalHeight, prevScale, newScale, y) diff --git a/lib/commonjs/ReactNativeZoomableView.js.map b/lib/commonjs/ReactNativeZoomableView.js.map index de3d33d..ca95dc4 100644 --- a/lib/commonjs/ReactNativeZoomableView.js.map +++ b/lib/commonjs/ReactNativeZoomableView.js.map @@ -1 +1 @@ -{"version":3,"sources":["ReactNativeZoomableView.tsx"],"names":["initialState","originalWidth","originalHeight","originalPageX","originalPageY","pinSize","width","height","ReactNativeZoomableView","Component","gestureStarted","v","_gestureStarted","constructor","props","Animated","ValueXY","x","y","Value","value","boundaryCrossedAnimInEffect","position","onStaticPinPositionChange","requestAnimationFrame","setTimeout","zoomSubjectWrapperRef","current","measureInWindow","setState","e","gestureState","onStartShouldSetPanResponder","_getZoomableViewEventObject","onLongPress","longPressTimeout","longPressDuration","onPanResponderGrant","panAnim","stopAnimation","zoomAnim","raisePin","gestureType","_resolveAndHandleTap","debugPoints","lastGestureCenterPosition","disableMomentum","panEnabled","disablePanOnInitialZoom","zoomLevel","initialZoom","vx","vy","start","clearTimeout","onPanResponderEnd","onZoomEnd","onShiftingEnd","staticPinPosition","_updateStaticPin","dropPin","onPanResponderMove","numberActiveTouches","_handlePanResponderGrant","_handlePanResponderEnd","lastGestureTouchDistance","_handlePinching","Math","abs","dx","dy","isShiftGesture","_handleShifting","now","Date","doubleTapFirstTapReleaseTimestamp","doubleTapDelay","doubleTapFirstTap","_addTouch","id","toString","isSecondTap","singleTapTimeoutId","_handleDoubleTap","state","nativeEvent","pageX","pageY","persist","tapX","tapY","timing","toValue","offsetX","offsetY","useNativeDriver","duration","onSingleTap","contentWidth","contentHeight","pinX","pinY","setValue","viewportPosition","imageSize","zoomableEvent","_staticPinPosition","gestureHandlers","PanResponder","create","_handleStartShouldSetPanResponder","_handlePanResponderMove","onPanResponderRelease","onPanResponderTerminate","evt","onPanResponderTerminationRequest","onShouldBlockNativeResponder","onStartShouldSetPanResponderCapture","onMoveShouldSetPanResponderCapture","zoomAnimatedValue","panAnimatedValueXY","initialOffsetX","initialOffsetY","addListener","animatePin","pinAnim","easing","Easing","out","ease","__setOffset","__getOffset","axis","offset","offsetState","__offsets","bindToBorders","containerSize","contentSize","boundOffset","panBoundaryPadding","boundariesApplied","toFixed","componentDidUpdate","prevProps","prevState","zoomEnabled","onTransformInvocationInitialized","_invokeOnTransform","successful","currState","originalMeasurementsChanged","staticPinPositionChanged","componentDidMount","grabZoomSubjectOriginalMeasurements","measureZoomSubjectInterval","setInterval","componentWillUnmount","clearInterval","zoomableViewEvent","onTransform","onStaticPinPositionMove","debouncedOnStaticPinPositionChange","overwriteObj","maxZoom","minZoom","pinchToZoomInSensitivity","pinchToZoomOutSensitivity","distance","onZoomBefore","zoomGrowthFromLastGestureState","pinchToZoomSensitivity","deltaGrowth","deltaGrowthAdjustedBySensitivity","newZoomLevel","gestureCenterPoint","zoomCenter","debug","_setPinchDebugPoints","oldOffsetX","oldOffsetY","oldScale","newScale","offsetShift","_calcOffsetShiftSinceLastGestureState","onZoomAfter","gestureResponderEvent","points","touches","movementSensibility","shift","shiftX","shiftY","moveX","moveY","_setNewOffsetPosition","newOffsetX","newOffsetY","onShiftingBefore","onShiftingAfter","touch","push","_removeTouch","splice","indexOf","onDoubleTapBefore","onDoubleTapAfter","doubleTapZoomToCenter","nextZoomStep","_getNextZoomStep","zoomPositionCoordinates","_zoomToLocation","zoomStep","prevScale","listenerId","removeListener","zoomTo","zoomBy","zoomLevelChange","moveTo","moveBy","offsetChangeX","offsetChangeY","render","staticPinIcon","children","visualTouchFeedbackEnabled","onStaticPinLongPress","onStaticPinPress","pinProps","styles","container","panHandlers","zoomSubject","style","transform","scale","getTranslateTransform","map","index","size","undefined","StyleSheet","alignItems","flex","justifyContent","overflow"],"mappings":"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","sourcesContent":["import React, { Component, createRef, RefObject } from 'react';\nimport {\n Animated,\n Easing,\n GestureResponderEvent,\n PanResponder,\n PanResponderCallbacks,\n PanResponderGestureState,\n PanResponderInstance,\n StyleSheet,\n View,\n} from 'react-native';\n\nimport {\n Vec2D,\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState,\n TouchPoint,\n ZoomableViewEvent,\n Size2D,\n} from './typings';\n\nimport { AnimatedTouchFeedback } from './components';\nimport { DebugTouchPoint } from './debugHelper';\nimport {\n calcGestureCenterPoint,\n calcGestureTouchDistance,\n calcNewScaledOffsetForZoomCentering,\n} from './helper';\nimport { applyPanBoundariesToOffset } from './helper/applyPanBoundariesToOffset';\nimport { viewportPositionToImagePosition } from './helper/coordinateConversion';\nimport { StaticPin } from './components/StaticPin';\nimport { debounce } from 'lodash';\nimport {\n getBoundaryCrossedAnim,\n getPanMomentumDecayAnim,\n getZoomToAnimation,\n} from './animations';\n\nconst initialState: ReactNativeZoomableViewState = {\n originalWidth: null,\n originalHeight: null,\n originalPageX: null,\n originalPageY: null,\n pinSize: { width: 0, height: 0 },\n};\n\nclass ReactNativeZoomableView extends Component<\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState\n> {\n zoomSubjectWrapperRef: RefObject;\n gestureHandlers: PanResponderInstance;\n doubleTapFirstTapReleaseTimestamp: number | undefined;\n\n static defaultProps = {\n zoomEnabled: true,\n panEnabled: true,\n initialZoom: 1,\n initialOffsetX: 0,\n initialOffsetY: 0,\n maxZoom: 1.5,\n minZoom: 0.5,\n pinchToZoomInSensitivity: 1,\n pinchToZoomOutSensitivity: 1,\n movementSensibility: 1,\n doubleTapDelay: 300,\n bindToBorders: true,\n zoomStep: 0.5,\n onLongPress: null,\n longPressDuration: 700,\n contentWidth: undefined,\n contentHeight: undefined,\n panBoundaryPadding: 0,\n visualTouchFeedbackEnabled: true,\n staticPinPosition: undefined,\n staticPinIcon: undefined,\n onStaticPinPositionChange: undefined,\n onStaticPinPositionMove: undefined,\n animatePin: true,\n disablePanOnInitialZoom: false,\n };\n\n private panAnim = new Animated.ValueXY({ x: 0, y: 0 });\n private zoomAnim = new Animated.Value(1);\n private pinAnim = new Animated.ValueXY({ x: 0, y: 0 });\n\n private __offsets = {\n x: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n y: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n };\n\n private zoomLevel = 1;\n private lastGestureCenterPosition: { x: number; y: number } | null = null;\n private lastGestureTouchDistance: number | null = null;\n private gestureType: 'pinch' | 'shift' | null;\n\n private _gestureStarted = false;\n private set gestureStarted(v: boolean) {\n this._gestureStarted = v;\n }\n\n public get gestureStarted() {\n return this._gestureStarted;\n }\n\n /**\n * Last press time (used to evaluate whether user double tapped)\n * @type {number}\n */\n private longPressTimeout: NodeJS.Timeout | null = null;\n private onTransformInvocationInitialized: boolean | undefined;\n private singleTapTimeoutId: NodeJS.Timeout | undefined;\n private touches: TouchPoint[] = [];\n private doubleTapFirstTap: TouchPoint | undefined;\n private measureZoomSubjectInterval: NodeJS.Timer | undefined;\n\n constructor(props: ReactNativeZoomableViewProps) {\n super(props);\n // This needs to be done before anything else to initialize the state.\n // Otherwise, the logic below may reference the state when it's undefined,\n // causing runtime errors.\n this.state = { ...initialState };\n\n this.gestureHandlers = PanResponder.create({\n onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,\n onPanResponderGrant: this._handlePanResponderGrant,\n onPanResponderMove: this._handlePanResponderMove,\n onPanResponderRelease: this._handlePanResponderEnd,\n onPanResponderTerminate: (evt, gestureState) => {\n // We should also call _handlePanResponderEnd\n // to properly perform cleanups when the gesture is terminated\n // (aka gesture handling responsibility is taken over by another component).\n // This also fixes a weird issue where\n // on real device, sometimes onPanResponderRelease is not called when you lift 2 fingers up,\n // but onPanResponderTerminate is called instead for no apparent reason.\n this._handlePanResponderEnd(evt, gestureState);\n this.props.onPanResponderTerminate?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n );\n },\n onPanResponderTerminationRequest: (evt, gestureState) =>\n !!this.props.onPanResponderTerminationRequest?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ),\n // Defaults to true to prevent parent components, such as React Navigation's tab view, from taking over as responder.\n onShouldBlockNativeResponder: (evt, gestureState) =>\n this.props.onShouldBlockNativeResponder?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ) ?? true,\n onStartShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onStartShouldSetPanResponderCapture?.(evt, gestureState),\n onMoveShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onMoveShouldSetPanResponderCapture?.(evt, gestureState),\n });\n\n this.zoomSubjectWrapperRef = createRef();\n\n if (this.props.zoomAnimatedValue)\n this.zoomAnim = this.props.zoomAnimatedValue;\n if (this.props.panAnimatedValueXY)\n this.panAnim = this.props.panAnimatedValueXY;\n\n if (this.props.initialZoom) this.zoomLevel = this.props.initialZoom;\n if (this.props.initialOffsetX != null)\n this.offsetX = this.props.initialOffsetX;\n if (this.props.initialOffsetY != null)\n this.offsetY = this.props.initialOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n this.panAnim.addListener(({ x, y }) => {\n this.offsetX = x;\n this.offsetY = y;\n });\n this.zoomAnim.addListener(({ value }) => {\n this.zoomLevel = value;\n });\n\n this.lastGestureTouchDistance = 150;\n\n this.gestureType = null;\n }\n\n private raisePin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: -10 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private dropPin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: 0 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private set offsetX(x: number) {\n this.__setOffset('x', x);\n }\n\n private set offsetY(y: number) {\n this.__setOffset('y', y);\n }\n\n private get offsetX() {\n return this.__getOffset('x');\n }\n\n private get offsetY() {\n return this.__getOffset('y');\n }\n\n private __setOffset(axis: 'x' | 'y', offset: number) {\n const offsetState = this.__offsets[axis];\n\n if (this.props.bindToBorders) {\n const containerSize =\n axis === 'x' ? this.state.originalWidth : this.state.originalHeight;\n const contentSize =\n axis === 'x'\n ? this.props.contentWidth || this.state.originalWidth\n : this.props.contentHeight || this.state.originalHeight;\n\n const boundOffset =\n contentSize && containerSize && this.props.panBoundaryPadding != null\n ? applyPanBoundariesToOffset(\n offset,\n containerSize,\n contentSize,\n this.zoomLevel,\n this.props.panBoundaryPadding\n )\n : offset;\n\n if (!this.gestureType && !offsetState.boundaryCrossedAnimInEffect) {\n const boundariesApplied =\n boundOffset !== offset &&\n boundOffset.toFixed(3) !== offset.toFixed(3);\n if (boundariesApplied) {\n offsetState.boundaryCrossedAnimInEffect = true;\n getBoundaryCrossedAnim(this.panAnim[axis], boundOffset).start(() => {\n offsetState.boundaryCrossedAnimInEffect = false;\n });\n return;\n }\n }\n }\n\n offsetState.value = offset;\n }\n\n private __getOffset(axis: 'x' | 'y') {\n return this.__offsets[axis].value;\n }\n\n componentDidUpdate(\n prevProps: ReactNativeZoomableViewProps,\n prevState: ReactNativeZoomableViewState\n ) {\n const { zoomEnabled, initialZoom } = this.props;\n if (prevProps.zoomEnabled && !zoomEnabled && initialZoom) {\n this.zoomLevel = initialZoom;\n this.zoomAnim.setValue(this.zoomLevel);\n }\n if (\n !this.onTransformInvocationInitialized &&\n this._invokeOnTransform().successful\n ) {\n this.panAnim.addListener(() => this._invokeOnTransform());\n this.zoomAnim.addListener(() => this._invokeOnTransform());\n this.onTransformInvocationInitialized = true;\n }\n\n const currState = this.state;\n const originalMeasurementsChanged =\n currState.originalHeight !== prevState.originalHeight ||\n currState.originalWidth !== prevState.originalWidth ||\n currState.originalPageX !== prevState.originalPageX ||\n currState.originalPageY !== prevState.originalPageY;\n\n const staticPinPositionChanged =\n prevProps.staticPinPosition?.x !== this.props.staticPinPosition?.x ||\n prevProps.staticPinPosition?.y !== this.props.staticPinPosition?.y;\n\n if (\n this.onTransformInvocationInitialized &&\n (originalMeasurementsChanged || staticPinPositionChanged)\n ) {\n this._invokeOnTransform();\n }\n }\n\n componentDidMount() {\n this.grabZoomSubjectOriginalMeasurements();\n // We've already run `grabZoomSubjectOriginalMeasurements` at various events\n // to make sure the measurements are promptly updated.\n // However, there might be cases we haven't accounted for, especially when\n // native processes are involved. To account for those cases,\n // we'll use an interval here to ensure we're always up-to-date.\n // The `setState` in `grabZoomSubjectOriginalMeasurements` won't trigger a rerender\n // if the values given haven't changed, so we're not running performance risk here.\n this.measureZoomSubjectInterval = setInterval(\n this.grabZoomSubjectOriginalMeasurements,\n 1e3\n );\n }\n\n componentWillUnmount() {\n this.measureZoomSubjectInterval &&\n clearInterval(this.measureZoomSubjectInterval);\n }\n\n debouncedOnStaticPinPositionChange = debounce(\n (position: Vec2D) => this.props.onStaticPinPositionChange?.(position),\n 100\n );\n\n /**\n * try to invoke onTransform\n * @private\n */\n _invokeOnTransform() {\n const zoomableViewEvent = this._getZoomableViewEventObject();\n const position = this._staticPinPosition();\n\n if (!zoomableViewEvent.originalWidth || !zoomableViewEvent.originalHeight)\n return { successful: false };\n\n this.props.onTransform?.(zoomableViewEvent);\n\n if (position) {\n this.props.onStaticPinPositionMove?.(position);\n this.debouncedOnStaticPinPositionChange(position);\n }\n\n return { successful: true };\n }\n\n /**\n * Returns additional information about components current state for external event hooks\n *\n * @returns {{}}\n * @private\n */\n _getZoomableViewEventObject(overwriteObj = {}): ZoomableViewEvent {\n return {\n zoomLevel: this.zoomLevel,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n originalHeight: this.state.originalHeight,\n originalWidth: this.state.originalWidth,\n originalPageX: this.state.originalPageX,\n originalPageY: this.state.originalPageY,\n ...overwriteObj,\n } as ZoomableViewEvent;\n }\n\n /**\n * Get the original box dimensions and save them for later use.\n * (They will be used to calculate boxBorders)\n *\n * @private\n */\n private grabZoomSubjectOriginalMeasurements = () => {\n // make sure we measure after animations are complete\n requestAnimationFrame(() => {\n // this setTimeout is here to fix a weird issue on iOS where the measurements are all `0`\n // when navigating back (react-navigation stack) from another view\n // while closing the keyboard at the same time\n setTimeout(() => {\n // In normal conditions, we're supposed to measure zoomSubject instead of its wrapper.\n // However, our zoomSubject may have been transformed by an initial zoomLevel or offset,\n // in which case these measurements will not represent the true \"original\" measurements.\n // We just need to make sure the zoomSubjectWrapper perfectly aligns with the zoomSubject\n // (no border, space, or anything between them)\n const zoomSubjectWrapperRef = this.zoomSubjectWrapperRef;\n // we don't wanna measure when zoomSubjectWrapperRef is not yet available or has been unmounted\n zoomSubjectWrapperRef.current?.measureInWindow(\n (x, y, width, height) => {\n // When the component is off-screen, these become all 0s, so we don't set them\n // to avoid messing up calculations, especially ones that are done right after\n // the component transitions from hidden to visible.\n if (!x && !y && !width && !height) return;\n this.setState({\n originalWidth: width,\n originalHeight: height,\n originalPageX: x,\n originalPageY: y,\n });\n }\n );\n });\n });\n };\n\n /**\n * Handles the start of touch events and checks for taps\n *\n * @param e\n * @param gestureState\n * @returns {boolean}\n *\n * @private\n */\n _handleStartShouldSetPanResponder = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onStartShouldSetPanResponder) {\n this.props.onStartShouldSetPanResponder(\n e,\n gestureState,\n this._getZoomableViewEventObject(),\n false\n );\n }\n\n // Always set pan responder on start\n // of gesture so we can handle tap.\n // \"Pan threshold validation\" will be handled\n // in `onPanResponderMove` instead of in `onMoveShouldSetPanResponder`\n return true;\n };\n\n /**\n * Calculates pinch distance\n *\n * @param e\n * @param gestureState\n * @private\n */\n _handlePanResponderGrant: NonNullable<\n PanResponderCallbacks['onPanResponderGrant']\n > = (e, gestureState) => {\n if (this.props.onLongPress) {\n this.longPressTimeout = setTimeout(() => {\n this.props.onLongPress?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n this.longPressTimeout = null;\n }, this.props.longPressDuration);\n }\n\n this.props.onPanResponderGrant?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n this.panAnim.stopAnimation();\n this.zoomAnim.stopAnimation();\n this.gestureStarted = true;\n\n this.raisePin();\n };\n\n /**\n * Handles the end of touch events\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderEnd: NonNullable<\n PanResponderCallbacks['onPanResponderEnd']\n > = (e, gestureState) => {\n if (!this.gestureType) {\n this._resolveAndHandleTap(e);\n }\n\n this.setState({ debugPoints: [] });\n\n this.lastGestureCenterPosition = null;\n\n const disableMomentum =\n this.props.disableMomentum ||\n (this.props.panEnabled &&\n this.gestureType === 'shift' &&\n this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom);\n\n // Trigger final shift animation unless disablePanOnInitialZoom is set and we're on the initial zoom level\n // or disableMomentum\n if (!disableMomentum) {\n getPanMomentumDecayAnim(this.panAnim, {\n x: gestureState.vx / this.zoomLevel,\n y: gestureState.vy / this.zoomLevel,\n }).start();\n }\n\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n this.props.onPanResponderEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n if (this.gestureType === 'pinch') {\n this.props.onZoomEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n } else if (this.gestureType === 'shift') {\n this.props.onShiftingEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n if (this.props.staticPinPosition) {\n this._updateStaticPin();\n }\n\n this.dropPin();\n\n this.gestureType = null;\n this.gestureStarted = false;\n };\n\n /**\n * Handles the actual movement of our pan responder\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderMove = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onPanResponderMove) {\n if (\n this.props.onPanResponderMove(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return false;\n }\n }\n\n // Only supports 2 touches and below,\n // any invalid number will cause the gesture to end.\n if (gestureState.numberActiveTouches <= 2) {\n if (!this.gestureStarted) {\n this._handlePanResponderGrant(e, gestureState);\n }\n } else {\n if (this.gestureStarted) {\n this._handlePanResponderEnd(e, gestureState);\n }\n return true;\n }\n\n if (gestureState.numberActiveTouches === 2) {\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'pinch') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n this.lastGestureTouchDistance = calcGestureTouchDistance(\n e,\n gestureState\n );\n }\n this.gestureType = 'pinch';\n this._handlePinching(e, gestureState);\n } else if (gestureState.numberActiveTouches === 1) {\n if (\n this.longPressTimeout &&\n (Math.abs(gestureState.dx) > 5 || Math.abs(gestureState.dy) > 5)\n ) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'shift') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n }\n\n const { dx, dy } = gestureState;\n const isShiftGesture = Math.abs(dx) > 2 || Math.abs(dy) > 2;\n if (isShiftGesture) {\n this.gestureType = 'shift';\n this._handleShifting(gestureState);\n }\n }\n };\n\n /**\n * Handles the pinch movement and zooming\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePinching(\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) {\n if (!this.props.zoomEnabled) return;\n\n const {\n maxZoom,\n minZoom,\n pinchToZoomInSensitivity,\n pinchToZoomOutSensitivity,\n } = this.props;\n\n const distance = calcGestureTouchDistance(e, gestureState);\n\n if (\n this.props.onZoomBefore &&\n this.props.onZoomBefore(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return;\n }\n\n if (!distance) return;\n if (!this.lastGestureTouchDistance) return;\n\n // define the new zoom level and take zoom level sensitivity into consideration\n const zoomGrowthFromLastGestureState =\n distance / this.lastGestureTouchDistance;\n this.lastGestureTouchDistance = distance;\n\n const pinchToZoomSensitivity =\n zoomGrowthFromLastGestureState < 1\n ? pinchToZoomOutSensitivity\n : pinchToZoomInSensitivity;\n\n if (pinchToZoomSensitivity == null) return;\n const deltaGrowth = zoomGrowthFromLastGestureState - 1;\n // 0 - no resistance\n // 10 - 90% resistance\n const deltaGrowthAdjustedBySensitivity =\n deltaGrowth * (1 - (pinchToZoomSensitivity * 9) / 100);\n\n let newZoomLevel = this.zoomLevel * (1 + deltaGrowthAdjustedBySensitivity);\n\n // make sure max and min zoom levels are respected\n if (maxZoom != null && newZoomLevel > maxZoom) {\n newZoomLevel = maxZoom;\n }\n\n if (minZoom != null && newZoomLevel < minZoom) {\n newZoomLevel = minZoom;\n }\n\n const gestureCenterPoint = calcGestureCenterPoint(e, gestureState);\n\n if (!gestureCenterPoint) return;\n if (this.state.originalPageX == null) return;\n if (this.state.originalPageY == null) return;\n\n let zoomCenter = {\n x: gestureCenterPoint.x - this.state.originalPageX,\n y: gestureCenterPoint.y - this.state.originalPageY,\n };\n\n if (this.props.staticPinPosition) {\n // When we use a static pin position, the zoom centre is the same as that position,\n // otherwise the pin moves around way too much while zooming.\n zoomCenter = {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n };\n }\n\n // Uncomment to debug\n this.props.debug && this._setPinchDebugPoints(e, zoomCenter);\n\n const { originalHeight, originalWidth } = this.state;\n\n const oldOffsetX = this.offsetX;\n const oldOffsetY = this.offsetY;\n const oldScale = this.zoomLevel;\n const newScale = newZoomLevel;\n\n if (!originalHeight || !originalWidth) return;\n\n let offsetY = calcNewScaledOffsetForZoomCentering(\n oldOffsetY,\n originalHeight,\n oldScale,\n newScale,\n zoomCenter.y\n );\n let offsetX = calcNewScaledOffsetForZoomCentering(\n oldOffsetX,\n originalWidth,\n oldScale,\n newScale,\n zoomCenter.x\n );\n\n const offsetShift =\n this._calcOffsetShiftSinceLastGestureState(gestureCenterPoint);\n if (offsetShift) {\n offsetX += offsetShift.x;\n offsetY += offsetShift.y;\n }\n\n this.offsetX = offsetX;\n this.offsetY = offsetY;\n this.zoomLevel = newScale;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n this.props.onZoomAfter?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n /**\n * Used to debug pinch events\n * @param gestureResponderEvent\n * @param zoomCenter\n * @param points\n */\n _setPinchDebugPoints(\n gestureResponderEvent: GestureResponderEvent,\n zoomCenter: Vec2D,\n ...points: Vec2D[]\n ) {\n const { touches } = gestureResponderEvent.nativeEvent;\n const { originalPageY, originalPageX } = this.state;\n if (originalPageX == null) return;\n if (originalPageY == null) return;\n\n this.setState({\n debugPoints: [\n {\n x: touches[0].pageX - originalPageX,\n y: touches[0].pageY - originalPageY,\n },\n {\n x: touches[1].pageX - originalPageX,\n y: touches[1].pageY - originalPageY,\n },\n zoomCenter,\n ...points,\n ],\n });\n }\n\n /**\n * Calculates the amount the offset should shift since the last position during panning\n *\n * @param {Vec2D} gestureCenterPoint\n *\n * @private\n */\n _calcOffsetShiftSinceLastGestureState(gestureCenterPoint: Vec2D) {\n const { movementSensibility } = this.props;\n\n let shift = null;\n\n if (this.lastGestureCenterPosition && movementSensibility) {\n const dx = gestureCenterPoint.x - this.lastGestureCenterPosition.x;\n const dy = gestureCenterPoint.y - this.lastGestureCenterPosition.y;\n\n const shiftX = dx / this.zoomLevel / movementSensibility;\n const shiftY = dy / this.zoomLevel / movementSensibility;\n\n shift = {\n x: shiftX,\n y: shiftY,\n };\n }\n\n this.lastGestureCenterPosition = gestureCenterPoint;\n\n return shift;\n }\n\n /**\n * Handles movement by tap and move\n *\n * @param gestureState\n *\n * @private\n */\n _handleShifting(gestureState: PanResponderGestureState) {\n // Skips shifting if panEnabled is false or disablePanOnInitialZoom is true and we're on the initial zoom level\n if (\n !this.props.panEnabled ||\n (this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom)\n ) {\n return;\n }\n const shift = this._calcOffsetShiftSinceLastGestureState({\n x: gestureState.moveX,\n y: gestureState.moveY,\n });\n if (!shift) return;\n\n const offsetX = this.offsetX + shift.x;\n const offsetY = this.offsetY + shift.y;\n\n if (\n this.props.debug &&\n this.state.originalPageX &&\n this.state.originalPageY\n ) {\n const x = gestureState.moveX - this.state.originalPageX;\n const y = gestureState.moveY - this.state.originalPageY;\n this.setState({ debugPoints: [{ x, y }] });\n }\n\n this._setNewOffsetPosition(offsetX, offsetY);\n\n this.raisePin();\n }\n\n /**\n * Set the state to offset moved\n *\n * @param {number} newOffsetX\n * @param {number} newOffsetY\n * @returns\n */\n _setNewOffsetPosition(newOffsetX: number, newOffsetY: number) {\n const { onShiftingBefore, onShiftingAfter } = this.props;\n\n if (onShiftingBefore?.(null, null, this._getZoomableViewEventObject())) {\n return;\n }\n\n this.offsetX = newOffsetX;\n this.offsetY = newOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n onShiftingAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Check whether the press event is double tap\n * or single tap and handle the event accordingly\n *\n * @param e\n *\n * @private\n */\n private _resolveAndHandleTap = (e: GestureResponderEvent) => {\n const now = Date.now();\n if (\n this.doubleTapFirstTapReleaseTimestamp &&\n this.props.doubleTapDelay &&\n now - this.doubleTapFirstTapReleaseTimestamp < this.props.doubleTapDelay\n ) {\n this.doubleTapFirstTap &&\n this._addTouch({\n ...this.doubleTapFirstTap,\n id: now.toString(),\n isSecondTap: true,\n });\n this.singleTapTimeoutId && clearTimeout(this.singleTapTimeoutId);\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n delete this.doubleTapFirstTap;\n this._handleDoubleTap(e);\n } else if (this.state.originalPageX && this.state.originalPageY) {\n this.doubleTapFirstTapReleaseTimestamp = now;\n this.doubleTapFirstTap = {\n id: now.toString(),\n x: e.nativeEvent.pageX - this.state.originalPageX,\n y: e.nativeEvent.pageY - this.state.originalPageY,\n };\n this._addTouch(this.doubleTapFirstTap);\n\n // persist event so e.nativeEvent is preserved after a timeout delay\n e.persist();\n this.singleTapTimeoutId = setTimeout(() => {\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n\n // Pan to the tapped location\n if (this.props.staticPinPosition && this.doubleTapFirstTap) {\n const tapX =\n this.props.staticPinPosition.x - this.doubleTapFirstTap.x;\n const tapY =\n this.props.staticPinPosition.y - this.doubleTapFirstTap.y;\n\n Animated.timing(this.panAnim, {\n toValue: {\n x: this.offsetX + tapX / this.zoomLevel,\n y: this.offsetY + tapY / this.zoomLevel,\n },\n useNativeDriver: true,\n duration: 200,\n }).start(() => {\n this._updateStaticPin();\n });\n }\n\n this.props.onSingleTap?.(e, this._getZoomableViewEventObject());\n }, this.props.doubleTapDelay);\n }\n };\n\n moveStaticPinTo = (position: Vec2D) => {\n const { originalWidth, originalHeight } = this.state;\n const { staticPinPosition, contentWidth, contentHeight } = this.props;\n\n if (!staticPinPosition) return;\n if (!originalWidth || !originalHeight) return;\n if (!contentWidth || !contentHeight) return;\n\n // Offset for the static pin\n const pinX = staticPinPosition.x - originalWidth / 2;\n const pinY = staticPinPosition.y - originalHeight / 2;\n\n this.offsetX = contentWidth / 2 - position.x + pinX / this.zoomLevel;\n this.offsetY = contentHeight / 2 - position.y + pinY / this.zoomLevel;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n };\n\n private _staticPinPosition = () => {\n if (!this.props.staticPinPosition) return;\n if (!this.props.contentWidth || !this.props.contentHeight) return;\n\n return viewportPositionToImagePosition({\n viewportPosition: {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n },\n imageSize: {\n height: this.props.contentHeight,\n width: this.props.contentWidth,\n },\n zoomableEvent: {\n ...this._getZoomableViewEventObject(),\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n zoomLevel: this.zoomLevel,\n },\n });\n };\n\n private _updateStaticPin = () => {\n const position = this._staticPinPosition();\n if (!position) return;\n this.props.onStaticPinPositionChange?.(position);\n };\n\n private _addTouch(touch: TouchPoint) {\n this.touches.push(touch);\n this.setState({ touches: [...this.touches] });\n }\n\n private _removeTouch(touch: TouchPoint) {\n this.touches.splice(this.touches.indexOf(touch), 1);\n this.setState({ touches: [...this.touches] });\n }\n\n /**\n * Handles the double tap event\n *\n * @param e\n *\n * @private\n */\n _handleDoubleTap(e: GestureResponderEvent) {\n const { onDoubleTapBefore, onDoubleTapAfter, doubleTapZoomToCenter } =\n this.props;\n\n onDoubleTapBefore?.(e, this._getZoomableViewEventObject());\n\n const nextZoomStep = this._getNextZoomStep();\n if (nextZoomStep == null) return;\n\n const { originalPageX, originalPageY } = this.state;\n if (originalPageX == null) return;\n if (originalPageY == null) return;\n\n // define new zoom position coordinates\n const zoomPositionCoordinates = {\n x: e.nativeEvent.pageX - originalPageX,\n y: e.nativeEvent.pageY - originalPageY,\n };\n\n // if doubleTapZoomToCenter enabled -> always zoom to center instead\n if (doubleTapZoomToCenter) {\n zoomPositionCoordinates.x = 0;\n zoomPositionCoordinates.y = 0;\n }\n\n this._zoomToLocation(\n zoomPositionCoordinates.x,\n zoomPositionCoordinates.y,\n nextZoomStep\n );\n\n onDoubleTapAfter?.(\n e,\n this._getZoomableViewEventObject({ zoomLevel: nextZoomStep })\n );\n }\n\n /**\n * Returns the next zoom step based on current step and zoomStep property.\n * If we are zoomed all the way in -> return to initialzoom\n *\n * @returns {*}\n */\n _getNextZoomStep() {\n const { zoomStep, maxZoom, initialZoom } = this.props;\n const { zoomLevel } = this;\n\n if (maxZoom == null) return;\n\n if (zoomLevel.toFixed(2) === maxZoom.toFixed(2)) {\n return initialZoom;\n }\n\n if (zoomStep == null) return;\n\n const nextZoomStep = zoomLevel * (1 + zoomStep);\n if (nextZoomStep > maxZoom) {\n return maxZoom;\n }\n\n return nextZoomStep;\n }\n\n /**\n * Zooms to a specific location in our view\n *\n * @param x\n * @param y\n * @param newZoomLevel\n *\n * @private\n */\n _zoomToLocation(x: number, y: number, newZoomLevel: number) {\n if (!this.props.zoomEnabled) return;\n if (this.state.originalWidth == null) return;\n if (this.state.originalHeight == null) return;\n\n this.props.onZoomBefore?.(null, null, this._getZoomableViewEventObject());\n\n // == Perform Zoom Animation ==\n // Calculates panAnim values based on changes in zoomAnim.\n let prevScale = this.zoomLevel;\n // Since zoomAnim is calculated in native driver,\n // it will jitter panAnim once in a while,\n // because here panAnim is being calculated in js.\n // However the jittering should mostly occur in simulator.\n const listenerId = this.zoomAnim.addListener(({ value: newScale }) => {\n if (this.state.originalWidth == null) return;\n if (this.state.originalHeight == null) return;\n this.panAnim.setValue({\n x: calcNewScaledOffsetForZoomCentering(\n this.offsetX,\n this.state.originalWidth,\n prevScale,\n newScale,\n x\n ),\n y: calcNewScaledOffsetForZoomCentering(\n this.offsetY,\n this.state.originalHeight,\n prevScale,\n newScale,\n y\n ),\n });\n prevScale = newScale;\n });\n getZoomToAnimation(this.zoomAnim, newZoomLevel).start(() => {\n this.zoomAnim.removeListener(listenerId);\n });\n // == Zoom Animation Ends ==\n\n this.props.onZoomAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Zooms to a specificied zoom level.\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number} newZoomLevel\n *\n * @return {bool}\n */\n zoomTo(newZoomLevel: number) {\n if (\n // if we would go out of our min/max limits -> abort\n (this.props.maxZoom && newZoomLevel > this.props.maxZoom) ||\n (this.props.minZoom && newZoomLevel < this.props.minZoom)\n )\n return false;\n\n this._zoomToLocation(0, 0, newZoomLevel);\n return true;\n }\n\n /**\n * Zooms in or out by a specified change level\n * Use a positive number for `zoomLevelChange` to zoom in\n * Use a negative number for `zoomLevelChange` to zoom out\n *\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number | null} zoomLevelChange\n *\n * @return {bool}\n */\n zoomBy(zoomLevelChange: number) {\n // if no zoom level Change given -> just use zoom step\n zoomLevelChange ||= this.props.zoomStep || 0;\n return this.zoomTo(this.zoomLevel + zoomLevelChange);\n }\n\n /**\n * Moves the zoomed view to a specified position\n * Returns a promise when finished\n *\n * @param {number} newOffsetX the new position we want to move it to (x-axis)\n * @param {number} newOffsetY the new position we want to move it to (y-axis)\n *\n * @return {bool}\n */\n moveTo(newOffsetX: number, newOffsetY: number) {\n const { originalWidth, originalHeight } = this.state;\n if (!originalWidth || !originalHeight) return;\n\n const offsetX = (newOffsetX - originalWidth / 2) / this.zoomLevel;\n const offsetY = (newOffsetY - originalHeight / 2) / this.zoomLevel;\n\n this._setNewOffsetPosition(-offsetX, -offsetY);\n }\n\n /**\n * Moves the zoomed view by a certain amount.\n *\n * Returns a promise when finished\n *\n * @param {number} offsetChangeX the amount we want to move the offset by (x-axis)\n * @param {number} offsetChangeY the amount we want to move the offset by (y-axis)\n *\n * @return {bool}\n */\n moveBy(offsetChangeX: number, offsetChangeY: number) {\n const offsetX =\n (this.offsetX * this.zoomLevel - offsetChangeX) / this.zoomLevel;\n const offsetY =\n (this.offsetY * this.zoomLevel - offsetChangeY) / this.zoomLevel;\n\n this._setNewOffsetPosition(offsetX, offsetY);\n }\n\n render() {\n const {\n staticPinIcon,\n children,\n visualTouchFeedbackEnabled,\n doubleTapDelay,\n staticPinPosition,\n onStaticPinLongPress,\n onStaticPinPress,\n pinProps,\n } = this.props;\n const { pinSize, touches, debugPoints = [] } = this.state;\n\n return (\n \n \n {children}\n \n\n {visualTouchFeedbackEnabled &&\n touches?.map(\n (touch) =>\n doubleTapDelay && (\n {\n this._removeTouch(touch);\n }}\n />\n )\n )}\n\n {/* For Debugging Only */}\n {debugPoints.map(({ x, y }, index) => {\n return ;\n })}\n\n {staticPinPosition && (\n {\n this.setState({ pinSize: size });\n }}\n pinProps={pinProps}\n />\n )}\n \n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n overflow: 'hidden',\n position: 'relative',\n },\n zoomSubject: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n width: '100%',\n },\n});\n\nexport default ReactNativeZoomableView;\n\nexport { ReactNativeZoomableView };\n"]} \ No newline at end of file +{"version":3,"sources":["ReactNativeZoomableView.tsx"],"names":["initialState","originalWidth","originalHeight","originalPageX","originalPageY","pinSize","width","height","ReactNativeZoomableView","Component","gestureStarted","v","_gestureStarted","constructor","props","Animated","ValueXY","x","y","Value","value","boundaryCrossedAnimInEffect","position","onStaticPinPositionChange","requestAnimationFrame","setTimeout","zoomSubjectWrapperRef","current","measureInWindow","setState","e","gestureState","onStartShouldSetPanResponder","_getZoomableViewEventObject","onLongPress","longPressTimeout","longPressDuration","onPanResponderGrant","panAnim","stopAnimation","zoomAnim","raisePin","gestureType","_resolveAndHandleTap","debugPoints","lastGestureCenterPosition","disableMomentum","panEnabled","disablePanOnInitialZoom","zoomLevel","initialZoom","vx","vy","start","clearTimeout","onPanResponderEnd","onZoomEnd","onShiftingEnd","staticPinPosition","_updateStaticPin","dropPin","onPanResponderMove","numberActiveTouches","_handlePanResponderGrant","_handlePanResponderEnd","lastGestureTouchDistance","_handlePinching","Math","abs","dx","dy","isShiftGesture","_handleShifting","now","Date","doubleTapFirstTapReleaseTimestamp","doubleTapDelay","doubleTapFirstTap","_addTouch","id","toString","isSecondTap","singleTapTimeoutId","_handleDoubleTap","nativeEvent","pageX","state","pageY","persist","tapX","tapY","timing","toValue","offsetX","offsetY","useNativeDriver","duration","onSingleTap","contentWidth","contentHeight","pinX","pinY","setValue","viewportPosition","imageSize","zoomableEvent","_staticPinPosition","gestureHandlers","PanResponder","create","_handleStartShouldSetPanResponder","_handlePanResponderMove","onPanResponderRelease","onPanResponderTerminate","evt","onPanResponderTerminationRequest","onShouldBlockNativeResponder","onStartShouldSetPanResponderCapture","onMoveShouldSetPanResponderCapture","zoomAnimatedValue","panAnimatedValueXY","initialOffsetX","initialOffsetY","addListener","animatePin","pinAnim","easing","Easing","out","ease","__setOffset","__getOffset","axis","offset","offsetState","__offsets","bindToBorders","containerSize","contentSize","boundOffset","panBoundaryPadding","boundariesApplied","toFixed","componentDidUpdate","prevProps","prevState","zoomEnabled","onTransformInvocationInitialized","_invokeOnTransform","successful","currState","originalMeasurementsChanged","staticPinPositionChanged","componentDidMount","grabZoomSubjectOriginalMeasurements","measureZoomSubjectInterval","setInterval","componentWillUnmount","clearInterval","zoomableViewEvent","onTransform","onStaticPinPositionMove","debouncedOnStaticPinPositionChange","overwriteObj","maxZoom","minZoom","pinchToZoomInSensitivity","pinchToZoomOutSensitivity","distance","onZoomBefore","zoomGrowthFromLastGestureState","pinchToZoomSensitivity","deltaGrowth","deltaGrowthAdjustedBySensitivity","newZoomLevel","gestureCenterPoint","zoomCenter","debug","_setPinchDebugPoints","oldOffsetX","oldOffsetY","oldScale","newScale","offsetShift","_calcOffsetShiftSinceLastGestureState","onZoomAfter","gestureResponderEvent","points","touches","movementSensibility","shift","shiftX","shiftY","moveX","moveY","_setNewOffsetPosition","newOffsetX","newOffsetY","onShiftingBefore","onShiftingAfter","touch","push","_removeTouch","splice","indexOf","onDoubleTapBefore","onDoubleTapAfter","doubleTapZoomToCenter","nextZoomStep","_getNextZoomStep","zoomPositionCoordinates","_zoomToLocation","zoomStep","prevScale","listenerId","removeListener","zoomTo","zoomBy","zoomLevelChange","moveTo","moveBy","offsetChangeX","offsetChangeY","render","staticPinIcon","children","visualTouchFeedbackEnabled","onStaticPinLongPress","onStaticPinPress","pinProps","styles","container","panHandlers","zoomSubject","style","transform","scale","getTranslateTransform","map","index","size","undefined","StyleSheet","alignItems","flex","justifyContent","overflow"],"mappings":"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","sourcesContent":["import React, { Component, createRef, RefObject } from 'react';\nimport {\n Animated,\n Easing,\n GestureResponderEvent,\n PanResponder,\n PanResponderCallbacks,\n PanResponderGestureState,\n PanResponderInstance,\n StyleSheet,\n View,\n} from 'react-native';\n\nimport {\n Vec2D,\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState,\n TouchPoint,\n ZoomableViewEvent,\n Size2D,\n} from './typings';\n\nimport { AnimatedTouchFeedback } from './components';\nimport { DebugTouchPoint } from './debugHelper';\nimport {\n calcGestureCenterPoint,\n calcGestureTouchDistance,\n calcNewScaledOffsetForZoomCentering,\n} from './helper';\nimport { applyPanBoundariesToOffset } from './helper/applyPanBoundariesToOffset';\nimport { viewportPositionToImagePosition } from './helper/coordinateConversion';\nimport { StaticPin } from './components/StaticPin';\nimport { debounce } from 'lodash';\nimport {\n getBoundaryCrossedAnim,\n getPanMomentumDecayAnim,\n getZoomToAnimation,\n} from './animations';\n\nconst initialState: ReactNativeZoomableViewState = {\n originalWidth: 0,\n originalHeight: 0,\n originalPageX: 0,\n originalPageY: 0,\n pinSize: { width: 0, height: 0 },\n};\n\nclass ReactNativeZoomableView extends Component<\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState\n> {\n zoomSubjectWrapperRef: RefObject;\n gestureHandlers: PanResponderInstance;\n doubleTapFirstTapReleaseTimestamp: number | undefined;\n\n static defaultProps = {\n zoomEnabled: true,\n panEnabled: true,\n initialZoom: 1,\n initialOffsetX: 0,\n initialOffsetY: 0,\n maxZoom: 1.5,\n minZoom: 0.5,\n pinchToZoomInSensitivity: 1,\n pinchToZoomOutSensitivity: 1,\n movementSensibility: 1,\n doubleTapDelay: 300,\n bindToBorders: true,\n zoomStep: 0.5,\n onLongPress: null,\n longPressDuration: 700,\n contentWidth: undefined,\n contentHeight: undefined,\n panBoundaryPadding: 0,\n visualTouchFeedbackEnabled: true,\n staticPinPosition: undefined,\n staticPinIcon: undefined,\n onStaticPinPositionChange: undefined,\n onStaticPinPositionMove: undefined,\n animatePin: true,\n disablePanOnInitialZoom: false,\n };\n\n private panAnim = new Animated.ValueXY({ x: 0, y: 0 });\n private zoomAnim = new Animated.Value(1);\n private pinAnim = new Animated.ValueXY({ x: 0, y: 0 });\n\n private __offsets = {\n x: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n y: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n };\n\n private zoomLevel = 1;\n private lastGestureCenterPosition: { x: number; y: number } | null = null;\n private lastGestureTouchDistance: number | null = null;\n private gestureType: 'pinch' | 'shift' | null;\n\n private _gestureStarted = false;\n private set gestureStarted(v: boolean) {\n this._gestureStarted = v;\n }\n\n public get gestureStarted() {\n return this._gestureStarted;\n }\n\n /**\n * Last press time (used to evaluate whether user double tapped)\n * @type {number}\n */\n private longPressTimeout: NodeJS.Timeout | null = null;\n private onTransformInvocationInitialized: boolean | undefined;\n private singleTapTimeoutId: NodeJS.Timeout | undefined;\n private touches: TouchPoint[] = [];\n private doubleTapFirstTap: TouchPoint | undefined;\n private measureZoomSubjectInterval: NodeJS.Timer | undefined;\n\n constructor(props: ReactNativeZoomableViewProps) {\n super(props);\n // This needs to be done before anything else to initialize the state.\n // Otherwise, the logic below may reference the state when it's undefined,\n // causing runtime errors.\n this.state = { ...initialState };\n\n this.gestureHandlers = PanResponder.create({\n onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,\n onPanResponderGrant: this._handlePanResponderGrant,\n onPanResponderMove: this._handlePanResponderMove,\n onPanResponderRelease: this._handlePanResponderEnd,\n onPanResponderTerminate: (evt, gestureState) => {\n // We should also call _handlePanResponderEnd\n // to properly perform cleanups when the gesture is terminated\n // (aka gesture handling responsibility is taken over by another component).\n // This also fixes a weird issue where\n // on real device, sometimes onPanResponderRelease is not called when you lift 2 fingers up,\n // but onPanResponderTerminate is called instead for no apparent reason.\n this._handlePanResponderEnd(evt, gestureState);\n this.props.onPanResponderTerminate?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n );\n },\n onPanResponderTerminationRequest: (evt, gestureState) =>\n !!this.props.onPanResponderTerminationRequest?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ),\n // Defaults to true to prevent parent components, such as React Navigation's tab view, from taking over as responder.\n onShouldBlockNativeResponder: (evt, gestureState) =>\n this.props.onShouldBlockNativeResponder?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ) ?? true,\n onStartShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onStartShouldSetPanResponderCapture?.(evt, gestureState),\n onMoveShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onMoveShouldSetPanResponderCapture?.(evt, gestureState),\n });\n\n this.zoomSubjectWrapperRef = createRef();\n\n if (this.props.zoomAnimatedValue)\n this.zoomAnim = this.props.zoomAnimatedValue;\n if (this.props.panAnimatedValueXY)\n this.panAnim = this.props.panAnimatedValueXY;\n\n if (this.props.initialZoom) this.zoomLevel = this.props.initialZoom;\n if (this.props.initialOffsetX != null)\n this.offsetX = this.props.initialOffsetX;\n if (this.props.initialOffsetY != null)\n this.offsetY = this.props.initialOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n this.panAnim.addListener(({ x, y }) => {\n this.offsetX = x;\n this.offsetY = y;\n });\n this.zoomAnim.addListener(({ value }) => {\n this.zoomLevel = value;\n });\n\n this.lastGestureTouchDistance = 150;\n\n this.gestureType = null;\n }\n\n private raisePin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: -10 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private dropPin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: 0 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private set offsetX(x: number) {\n this.__setOffset('x', x);\n }\n\n private set offsetY(y: number) {\n this.__setOffset('y', y);\n }\n\n private get offsetX() {\n return this.__getOffset('x');\n }\n\n private get offsetY() {\n return this.__getOffset('y');\n }\n\n private __setOffset(axis: 'x' | 'y', offset: number) {\n const offsetState = this.__offsets[axis];\n\n if (this.props.bindToBorders) {\n const containerSize =\n axis === 'x' ? this.state.originalWidth : this.state.originalHeight;\n const contentSize =\n axis === 'x'\n ? this.props.contentWidth || this.state.originalWidth\n : this.props.contentHeight || this.state.originalHeight;\n\n const boundOffset =\n contentSize && containerSize && this.props.panBoundaryPadding != null\n ? applyPanBoundariesToOffset(\n offset,\n containerSize,\n contentSize,\n this.zoomLevel,\n this.props.panBoundaryPadding\n )\n : offset;\n\n if (!this.gestureType && !offsetState.boundaryCrossedAnimInEffect) {\n const boundariesApplied =\n boundOffset !== offset &&\n boundOffset.toFixed(3) !== offset.toFixed(3);\n if (boundariesApplied) {\n offsetState.boundaryCrossedAnimInEffect = true;\n getBoundaryCrossedAnim(this.panAnim[axis], boundOffset).start(() => {\n offsetState.boundaryCrossedAnimInEffect = false;\n });\n return;\n }\n }\n }\n\n offsetState.value = offset;\n }\n\n private __getOffset(axis: 'x' | 'y') {\n return this.__offsets[axis].value;\n }\n\n componentDidUpdate(\n prevProps: ReactNativeZoomableViewProps,\n prevState: ReactNativeZoomableViewState\n ) {\n const { zoomEnabled, initialZoom } = this.props;\n if (prevProps.zoomEnabled && !zoomEnabled && initialZoom) {\n this.zoomLevel = initialZoom;\n this.zoomAnim.setValue(this.zoomLevel);\n }\n if (\n !this.onTransformInvocationInitialized &&\n this._invokeOnTransform().successful\n ) {\n this.panAnim.addListener(() => this._invokeOnTransform());\n this.zoomAnim.addListener(() => this._invokeOnTransform());\n this.onTransformInvocationInitialized = true;\n }\n\n const currState = this.state;\n const originalMeasurementsChanged =\n currState.originalHeight !== prevState.originalHeight ||\n currState.originalWidth !== prevState.originalWidth ||\n currState.originalPageX !== prevState.originalPageX ||\n currState.originalPageY !== prevState.originalPageY;\n\n const staticPinPositionChanged =\n prevProps.staticPinPosition?.x !== this.props.staticPinPosition?.x ||\n prevProps.staticPinPosition?.y !== this.props.staticPinPosition?.y;\n\n if (\n this.onTransformInvocationInitialized &&\n (originalMeasurementsChanged || staticPinPositionChanged)\n ) {\n this._invokeOnTransform();\n }\n }\n\n componentDidMount() {\n this.grabZoomSubjectOriginalMeasurements();\n // We've already run `grabZoomSubjectOriginalMeasurements` at various events\n // to make sure the measurements are promptly updated.\n // However, there might be cases we haven't accounted for, especially when\n // native processes are involved. To account for those cases,\n // we'll use an interval here to ensure we're always up-to-date.\n // The `setState` in `grabZoomSubjectOriginalMeasurements` won't trigger a rerender\n // if the values given haven't changed, so we're not running performance risk here.\n this.measureZoomSubjectInterval = setInterval(\n this.grabZoomSubjectOriginalMeasurements,\n 1e3\n );\n }\n\n componentWillUnmount() {\n this.measureZoomSubjectInterval &&\n clearInterval(this.measureZoomSubjectInterval);\n }\n\n debouncedOnStaticPinPositionChange = debounce(\n (position: Vec2D) => this.props.onStaticPinPositionChange?.(position),\n 100\n );\n\n /**\n * try to invoke onTransform\n * @private\n */\n _invokeOnTransform() {\n const zoomableViewEvent = this._getZoomableViewEventObject();\n const position = this._staticPinPosition();\n\n if (!zoomableViewEvent.originalWidth || !zoomableViewEvent.originalHeight)\n return { successful: false };\n\n this.props.onTransform?.(zoomableViewEvent);\n\n if (position) {\n this.props.onStaticPinPositionMove?.(position);\n this.debouncedOnStaticPinPositionChange(position);\n }\n\n return { successful: true };\n }\n\n /**\n * Returns additional information about components current state for external event hooks\n *\n * @returns {{}}\n * @private\n */\n _getZoomableViewEventObject(overwriteObj = {}): ZoomableViewEvent {\n return {\n zoomLevel: this.zoomLevel,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n originalHeight: this.state.originalHeight,\n originalWidth: this.state.originalWidth,\n originalPageX: this.state.originalPageX,\n originalPageY: this.state.originalPageY,\n ...overwriteObj,\n } as ZoomableViewEvent;\n }\n\n /**\n * Get the original box dimensions and save them for later use.\n * (They will be used to calculate boxBorders)\n *\n * @private\n */\n private grabZoomSubjectOriginalMeasurements = () => {\n // make sure we measure after animations are complete\n requestAnimationFrame(() => {\n // this setTimeout is here to fix a weird issue on iOS where the measurements are all `0`\n // when navigating back (react-navigation stack) from another view\n // while closing the keyboard at the same time\n setTimeout(() => {\n // In normal conditions, we're supposed to measure zoomSubject instead of its wrapper.\n // However, our zoomSubject may have been transformed by an initial zoomLevel or offset,\n // in which case these measurements will not represent the true \"original\" measurements.\n // We just need to make sure the zoomSubjectWrapper perfectly aligns with the zoomSubject\n // (no border, space, or anything between them)\n const zoomSubjectWrapperRef = this.zoomSubjectWrapperRef;\n // we don't wanna measure when zoomSubjectWrapperRef is not yet available or has been unmounted\n zoomSubjectWrapperRef.current?.measureInWindow(\n (x, y, width, height) => {\n // When the component is off-screen, these become all 0s, so we don't set them\n // to avoid messing up calculations, especially ones that are done right after\n // the component transitions from hidden to visible.\n if (!x && !y && !width && !height) return;\n this.setState({\n originalWidth: width,\n originalHeight: height,\n originalPageX: x,\n originalPageY: y,\n });\n }\n );\n });\n });\n };\n\n /**\n * Handles the start of touch events and checks for taps\n *\n * @param e\n * @param gestureState\n * @returns {boolean}\n *\n * @private\n */\n _handleStartShouldSetPanResponder = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onStartShouldSetPanResponder) {\n this.props.onStartShouldSetPanResponder(\n e,\n gestureState,\n this._getZoomableViewEventObject(),\n false\n );\n }\n\n // Always set pan responder on start\n // of gesture so we can handle tap.\n // \"Pan threshold validation\" will be handled\n // in `onPanResponderMove` instead of in `onMoveShouldSetPanResponder`\n return true;\n };\n\n /**\n * Calculates pinch distance\n *\n * @param e\n * @param gestureState\n * @private\n */\n _handlePanResponderGrant: NonNullable<\n PanResponderCallbacks['onPanResponderGrant']\n > = (e, gestureState) => {\n if (this.props.onLongPress) {\n this.longPressTimeout = setTimeout(() => {\n this.props.onLongPress?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n this.longPressTimeout = null;\n }, this.props.longPressDuration);\n }\n\n this.props.onPanResponderGrant?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n this.panAnim.stopAnimation();\n this.zoomAnim.stopAnimation();\n this.gestureStarted = true;\n\n this.raisePin();\n };\n\n /**\n * Handles the end of touch events\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderEnd: NonNullable<\n PanResponderCallbacks['onPanResponderEnd']\n > = (e, gestureState) => {\n if (!this.gestureType) {\n this._resolveAndHandleTap(e);\n }\n\n this.setState({ debugPoints: [] });\n\n this.lastGestureCenterPosition = null;\n\n const disableMomentum =\n this.props.disableMomentum ||\n (this.props.panEnabled &&\n this.gestureType === 'shift' &&\n this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom);\n\n // Trigger final shift animation unless disablePanOnInitialZoom is set and we're on the initial zoom level\n // or disableMomentum\n if (!disableMomentum) {\n getPanMomentumDecayAnim(this.panAnim, {\n x: gestureState.vx / this.zoomLevel,\n y: gestureState.vy / this.zoomLevel,\n }).start();\n }\n\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n this.props.onPanResponderEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n if (this.gestureType === 'pinch') {\n this.props.onZoomEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n } else if (this.gestureType === 'shift') {\n this.props.onShiftingEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n if (this.props.staticPinPosition) {\n this._updateStaticPin();\n }\n\n this.dropPin();\n\n this.gestureType = null;\n this.gestureStarted = false;\n };\n\n /**\n * Handles the actual movement of our pan responder\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderMove = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onPanResponderMove) {\n if (\n this.props.onPanResponderMove(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return false;\n }\n }\n\n // Only supports 2 touches and below,\n // any invalid number will cause the gesture to end.\n if (gestureState.numberActiveTouches <= 2) {\n if (!this.gestureStarted) {\n this._handlePanResponderGrant(e, gestureState);\n }\n } else {\n if (this.gestureStarted) {\n this._handlePanResponderEnd(e, gestureState);\n }\n return true;\n }\n\n if (gestureState.numberActiveTouches === 2) {\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'pinch') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n this.lastGestureTouchDistance = calcGestureTouchDistance(\n e,\n gestureState\n );\n }\n this.gestureType = 'pinch';\n this._handlePinching(e, gestureState);\n } else if (gestureState.numberActiveTouches === 1) {\n if (\n this.longPressTimeout &&\n (Math.abs(gestureState.dx) > 5 || Math.abs(gestureState.dy) > 5)\n ) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'shift') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n }\n\n const { dx, dy } = gestureState;\n const isShiftGesture = Math.abs(dx) > 2 || Math.abs(dy) > 2;\n if (isShiftGesture) {\n this.gestureType = 'shift';\n this._handleShifting(gestureState);\n }\n }\n };\n\n /**\n * Handles the pinch movement and zooming\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePinching(\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) {\n if (!this.props.zoomEnabled) return;\n\n const {\n maxZoom,\n minZoom,\n pinchToZoomInSensitivity,\n pinchToZoomOutSensitivity,\n } = this.props;\n\n const distance = calcGestureTouchDistance(e, gestureState);\n\n if (\n this.props.onZoomBefore &&\n this.props.onZoomBefore(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return;\n }\n\n if (!distance) return;\n if (!this.lastGestureTouchDistance) return;\n\n // define the new zoom level and take zoom level sensitivity into consideration\n const zoomGrowthFromLastGestureState =\n distance / this.lastGestureTouchDistance;\n this.lastGestureTouchDistance = distance;\n\n const pinchToZoomSensitivity =\n zoomGrowthFromLastGestureState < 1\n ? pinchToZoomOutSensitivity\n : pinchToZoomInSensitivity;\n\n if (pinchToZoomSensitivity == null) return;\n const deltaGrowth = zoomGrowthFromLastGestureState - 1;\n // 0 - no resistance\n // 10 - 90% resistance\n const deltaGrowthAdjustedBySensitivity =\n deltaGrowth * (1 - (pinchToZoomSensitivity * 9) / 100);\n\n let newZoomLevel = this.zoomLevel * (1 + deltaGrowthAdjustedBySensitivity);\n\n // make sure max and min zoom levels are respected\n if (maxZoom != null && newZoomLevel > maxZoom) {\n newZoomLevel = maxZoom;\n }\n\n if (minZoom != null && newZoomLevel < minZoom) {\n newZoomLevel = minZoom;\n }\n\n const gestureCenterPoint = calcGestureCenterPoint(e, gestureState);\n\n if (!gestureCenterPoint) return;\n\n let zoomCenter = {\n x: gestureCenterPoint.x - this.state.originalPageX,\n y: gestureCenterPoint.y - this.state.originalPageY,\n };\n\n if (this.props.staticPinPosition) {\n // When we use a static pin position, the zoom centre is the same as that position,\n // otherwise the pin moves around way too much while zooming.\n zoomCenter = {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n };\n }\n\n // Uncomment to debug\n this.props.debug && this._setPinchDebugPoints(e, zoomCenter);\n\n const { originalHeight, originalWidth } = this.state;\n\n const oldOffsetX = this.offsetX;\n const oldOffsetY = this.offsetY;\n const oldScale = this.zoomLevel;\n const newScale = newZoomLevel;\n\n if (!originalHeight || !originalWidth) return;\n\n let offsetY = calcNewScaledOffsetForZoomCentering(\n oldOffsetY,\n originalHeight,\n oldScale,\n newScale,\n zoomCenter.y\n );\n let offsetX = calcNewScaledOffsetForZoomCentering(\n oldOffsetX,\n originalWidth,\n oldScale,\n newScale,\n zoomCenter.x\n );\n\n const offsetShift =\n this._calcOffsetShiftSinceLastGestureState(gestureCenterPoint);\n if (offsetShift) {\n offsetX += offsetShift.x;\n offsetY += offsetShift.y;\n }\n\n this.offsetX = offsetX;\n this.offsetY = offsetY;\n this.zoomLevel = newScale;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n this.props.onZoomAfter?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n /**\n * Used to debug pinch events\n * @param gestureResponderEvent\n * @param zoomCenter\n * @param points\n */\n _setPinchDebugPoints(\n gestureResponderEvent: GestureResponderEvent,\n zoomCenter: Vec2D,\n ...points: Vec2D[]\n ) {\n const { touches } = gestureResponderEvent.nativeEvent;\n const { originalPageY, originalPageX } = this.state;\n\n this.setState({\n debugPoints: [\n {\n x: touches[0].pageX - originalPageX,\n y: touches[0].pageY - originalPageY,\n },\n {\n x: touches[1].pageX - originalPageX,\n y: touches[1].pageY - originalPageY,\n },\n zoomCenter,\n ...points,\n ],\n });\n }\n\n /**\n * Calculates the amount the offset should shift since the last position during panning\n *\n * @param {Vec2D} gestureCenterPoint\n *\n * @private\n */\n _calcOffsetShiftSinceLastGestureState(gestureCenterPoint: Vec2D) {\n const { movementSensibility } = this.props;\n\n let shift = null;\n\n if (this.lastGestureCenterPosition && movementSensibility) {\n const dx = gestureCenterPoint.x - this.lastGestureCenterPosition.x;\n const dy = gestureCenterPoint.y - this.lastGestureCenterPosition.y;\n\n const shiftX = dx / this.zoomLevel / movementSensibility;\n const shiftY = dy / this.zoomLevel / movementSensibility;\n\n shift = {\n x: shiftX,\n y: shiftY,\n };\n }\n\n this.lastGestureCenterPosition = gestureCenterPoint;\n\n return shift;\n }\n\n /**\n * Handles movement by tap and move\n *\n * @param gestureState\n *\n * @private\n */\n _handleShifting(gestureState: PanResponderGestureState) {\n // Skips shifting if panEnabled is false or disablePanOnInitialZoom is true and we're on the initial zoom level\n if (\n !this.props.panEnabled ||\n (this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom)\n ) {\n return;\n }\n const shift = this._calcOffsetShiftSinceLastGestureState({\n x: gestureState.moveX,\n y: gestureState.moveY,\n });\n if (!shift) return;\n\n const offsetX = this.offsetX + shift.x;\n const offsetY = this.offsetY + shift.y;\n\n if (\n this.props.debug &&\n this.state.originalPageX &&\n this.state.originalPageY\n ) {\n const x = gestureState.moveX - this.state.originalPageX;\n const y = gestureState.moveY - this.state.originalPageY;\n this.setState({ debugPoints: [{ x, y }] });\n }\n\n this._setNewOffsetPosition(offsetX, offsetY);\n\n this.raisePin();\n }\n\n /**\n * Set the state to offset moved\n *\n * @param {number} newOffsetX\n * @param {number} newOffsetY\n * @returns\n */\n _setNewOffsetPosition(newOffsetX: number, newOffsetY: number) {\n const { onShiftingBefore, onShiftingAfter } = this.props;\n\n if (onShiftingBefore?.(null, null, this._getZoomableViewEventObject())) {\n return;\n }\n\n this.offsetX = newOffsetX;\n this.offsetY = newOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n onShiftingAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Check whether the press event is double tap\n * or single tap and handle the event accordingly\n *\n * @param e\n *\n * @private\n */\n private _resolveAndHandleTap = (e: GestureResponderEvent) => {\n const now = Date.now();\n if (\n this.doubleTapFirstTapReleaseTimestamp &&\n this.props.doubleTapDelay &&\n now - this.doubleTapFirstTapReleaseTimestamp < this.props.doubleTapDelay\n ) {\n this.doubleTapFirstTap &&\n this._addTouch({\n ...this.doubleTapFirstTap,\n id: now.toString(),\n isSecondTap: true,\n });\n this.singleTapTimeoutId && clearTimeout(this.singleTapTimeoutId);\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n delete this.doubleTapFirstTap;\n this._handleDoubleTap(e);\n } else {\n this.doubleTapFirstTapReleaseTimestamp = now;\n this.doubleTapFirstTap = {\n id: now.toString(),\n x: e.nativeEvent.pageX - this.state.originalPageX,\n y: e.nativeEvent.pageY - this.state.originalPageY,\n };\n this._addTouch(this.doubleTapFirstTap);\n\n // persist event so e.nativeEvent is preserved after a timeout delay\n e.persist();\n this.singleTapTimeoutId = setTimeout(() => {\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n\n // Pan to the tapped location\n if (this.props.staticPinPosition && this.doubleTapFirstTap) {\n const tapX =\n this.props.staticPinPosition.x - this.doubleTapFirstTap.x;\n const tapY =\n this.props.staticPinPosition.y - this.doubleTapFirstTap.y;\n\n Animated.timing(this.panAnim, {\n toValue: {\n x: this.offsetX + tapX / this.zoomLevel,\n y: this.offsetY + tapY / this.zoomLevel,\n },\n useNativeDriver: true,\n duration: 200,\n }).start(() => {\n this._updateStaticPin();\n });\n }\n\n this.props.onSingleTap?.(e, this._getZoomableViewEventObject());\n }, this.props.doubleTapDelay);\n }\n };\n\n moveStaticPinTo = (position: Vec2D, duration?: number) => {\n const { originalWidth, originalHeight } = this.state;\n const { staticPinPosition, contentWidth, contentHeight } = this.props;\n\n if (!staticPinPosition) return;\n if (!originalWidth || !originalHeight) return;\n if (!contentWidth || !contentHeight) return;\n\n // Offset for the static pin\n const pinX = staticPinPosition.x - originalWidth / 2;\n const pinY = staticPinPosition.y - originalHeight / 2;\n\n this.offsetX = contentWidth / 2 - position.x + pinX / this.zoomLevel;\n this.offsetY = contentHeight / 2 - position.y + pinY / this.zoomLevel;\n\n if (duration) {\n Animated.timing(this.panAnim, {\n toValue: { x: this.offsetX, y: this.offsetY },\n useNativeDriver: true,\n duration,\n }).start();\n } else {\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n }\n };\n\n private _staticPinPosition = () => {\n if (!this.props.staticPinPosition) return;\n if (!this.props.contentWidth || !this.props.contentHeight) return;\n\n return viewportPositionToImagePosition({\n viewportPosition: {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n },\n imageSize: {\n height: this.props.contentHeight,\n width: this.props.contentWidth,\n },\n zoomableEvent: {\n ...this._getZoomableViewEventObject(),\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n zoomLevel: this.zoomLevel,\n },\n });\n };\n\n private _updateStaticPin = () => {\n const position = this._staticPinPosition();\n if (!position) return;\n this.props.onStaticPinPositionChange?.(position);\n };\n\n private _addTouch(touch: TouchPoint) {\n this.touches.push(touch);\n this.setState({ touches: [...this.touches] });\n }\n\n private _removeTouch(touch: TouchPoint) {\n this.touches.splice(this.touches.indexOf(touch), 1);\n this.setState({ touches: [...this.touches] });\n }\n\n /**\n * Handles the double tap event\n *\n * @param e\n *\n * @private\n */\n _handleDoubleTap(e: GestureResponderEvent) {\n const { onDoubleTapBefore, onDoubleTapAfter, doubleTapZoomToCenter } =\n this.props;\n\n onDoubleTapBefore?.(e, this._getZoomableViewEventObject());\n\n const nextZoomStep = this._getNextZoomStep();\n if (nextZoomStep == null) return;\n\n const { originalPageX, originalPageY } = this.state;\n\n // define new zoom position coordinates\n const zoomPositionCoordinates = {\n x: e.nativeEvent.pageX - originalPageX,\n y: e.nativeEvent.pageY - originalPageY,\n };\n\n // if doubleTapZoomToCenter enabled -> always zoom to center instead\n if (doubleTapZoomToCenter) {\n zoomPositionCoordinates.x = 0;\n zoomPositionCoordinates.y = 0;\n }\n\n this._zoomToLocation(\n zoomPositionCoordinates.x,\n zoomPositionCoordinates.y,\n nextZoomStep\n );\n\n onDoubleTapAfter?.(\n e,\n this._getZoomableViewEventObject({ zoomLevel: nextZoomStep })\n );\n }\n\n /**\n * Returns the next zoom step based on current step and zoomStep property.\n * If we are zoomed all the way in -> return to initialzoom\n *\n * @returns {*}\n */\n _getNextZoomStep() {\n const { zoomStep, maxZoom, initialZoom } = this.props;\n const { zoomLevel } = this;\n\n if (maxZoom == null) return;\n\n if (zoomLevel.toFixed(2) === maxZoom.toFixed(2)) {\n return initialZoom;\n }\n\n if (zoomStep == null) return;\n\n const nextZoomStep = zoomLevel * (1 + zoomStep);\n if (nextZoomStep > maxZoom) {\n return maxZoom;\n }\n\n return nextZoomStep;\n }\n\n /**\n * Zooms to a specific location in our view\n *\n * @param x\n * @param y\n * @param newZoomLevel\n *\n * @private\n */\n _zoomToLocation(x: number, y: number, newZoomLevel: number) {\n if (!this.props.zoomEnabled) return;\n\n this.props.onZoomBefore?.(null, null, this._getZoomableViewEventObject());\n\n // == Perform Zoom Animation ==\n // Calculates panAnim values based on changes in zoomAnim.\n let prevScale = this.zoomLevel;\n // Since zoomAnim is calculated in native driver,\n // it will jitter panAnim once in a while,\n // because here panAnim is being calculated in js.\n // However the jittering should mostly occur in simulator.\n const listenerId = this.zoomAnim.addListener(({ value: newScale }) => {\n this.panAnim.setValue({\n x: calcNewScaledOffsetForZoomCentering(\n this.offsetX,\n this.state.originalWidth,\n prevScale,\n newScale,\n x\n ),\n y: calcNewScaledOffsetForZoomCentering(\n this.offsetY,\n this.state.originalHeight,\n prevScale,\n newScale,\n y\n ),\n });\n prevScale = newScale;\n });\n getZoomToAnimation(this.zoomAnim, newZoomLevel).start(() => {\n this.zoomAnim.removeListener(listenerId);\n });\n // == Zoom Animation Ends ==\n\n this.props.onZoomAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Zooms to a specificied zoom level.\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number} newZoomLevel\n *\n * @return {bool}\n */\n zoomTo(newZoomLevel: number) {\n if (\n // if we would go out of our min/max limits -> abort\n (this.props.maxZoom && newZoomLevel > this.props.maxZoom) ||\n (this.props.minZoom && newZoomLevel < this.props.minZoom)\n )\n return false;\n\n this._zoomToLocation(0, 0, newZoomLevel);\n return true;\n }\n\n /**\n * Zooms in or out by a specified change level\n * Use a positive number for `zoomLevelChange` to zoom in\n * Use a negative number for `zoomLevelChange` to zoom out\n *\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number | null} zoomLevelChange\n *\n * @return {bool}\n */\n zoomBy(zoomLevelChange: number) {\n // if no zoom level Change given -> just use zoom step\n zoomLevelChange ||= this.props.zoomStep || 0;\n return this.zoomTo(this.zoomLevel + zoomLevelChange);\n }\n\n /**\n * Moves the zoomed view to a specified position\n * Returns a promise when finished\n *\n * @param {number} newOffsetX the new position we want to move it to (x-axis)\n * @param {number} newOffsetY the new position we want to move it to (y-axis)\n *\n * @return {bool}\n */\n moveTo(newOffsetX: number, newOffsetY: number) {\n const { originalWidth, originalHeight } = this.state;\n if (!originalWidth || !originalHeight) return;\n\n const offsetX = (newOffsetX - originalWidth / 2) / this.zoomLevel;\n const offsetY = (newOffsetY - originalHeight / 2) / this.zoomLevel;\n\n this._setNewOffsetPosition(-offsetX, -offsetY);\n }\n\n /**\n * Moves the zoomed view by a certain amount.\n *\n * Returns a promise when finished\n *\n * @param {number} offsetChangeX the amount we want to move the offset by (x-axis)\n * @param {number} offsetChangeY the amount we want to move the offset by (y-axis)\n *\n * @return {bool}\n */\n moveBy(offsetChangeX: number, offsetChangeY: number) {\n const offsetX =\n (this.offsetX * this.zoomLevel - offsetChangeX) / this.zoomLevel;\n const offsetY =\n (this.offsetY * this.zoomLevel - offsetChangeY) / this.zoomLevel;\n\n this._setNewOffsetPosition(offsetX, offsetY);\n }\n\n render() {\n const {\n staticPinIcon,\n children,\n visualTouchFeedbackEnabled,\n doubleTapDelay,\n staticPinPosition,\n onStaticPinLongPress,\n onStaticPinPress,\n pinProps,\n } = this.props;\n const { pinSize, touches, debugPoints = [] } = this.state;\n\n return (\n \n \n {children}\n \n\n {visualTouchFeedbackEnabled &&\n touches?.map(\n (touch) =>\n doubleTapDelay && (\n {\n this._removeTouch(touch);\n }}\n />\n )\n )}\n\n {/* For Debugging Only */}\n {debugPoints.map(({ x, y }, index) => {\n return ;\n })}\n\n {staticPinPosition && (\n {\n this.setState({ pinSize: size });\n }}\n pinProps={pinProps}\n />\n )}\n \n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n overflow: 'hidden',\n position: 'relative',\n },\n zoomSubject: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n width: '100%',\n },\n});\n\nexport default ReactNativeZoomableView;\n\nexport { ReactNativeZoomableView };\n"]} \ No newline at end of file diff --git a/lib/commonjs/typings/index.js.map b/lib/commonjs/typings/index.js.map index 541c515..be56215 100644 --- a/lib/commonjs/typings/index.js.map +++ b/lib/commonjs/typings/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["index.ts"],"names":["SwipeDirection"],"mappings":";;;;;;IAOYA,c;;;WAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;GAAAA,c,8BAAAA,c","sourcesContent":["import {\n Animated,\n GestureResponderEvent,\n PanResponderGestureState,\n ViewProps,\n} from 'react-native';\n\nexport enum SwipeDirection {\n SWIPE_UP = 'SWIPE_UP',\n SWIPE_DOWN = 'SWIPE_DOWN',\n SWIPE_LEFT = 'SWIPE_LEFT',\n SWIPE_RIGHT = 'SWIPE_RIGHT',\n}\n\nexport interface ZoomableViewEvent {\n zoomLevel: number;\n offsetX: number;\n offsetY: number;\n originalHeight: number;\n originalWidth: number;\n originalPageX: number;\n originalPageY: number;\n}\n\nexport interface ReactNativeZoomableViewProps extends ViewProps {\n // options\n zoomEnabled?: boolean;\n panEnabled?: boolean;\n initialZoom?: number;\n initialOffsetX?: number;\n initialOffsetY?: number;\n contentWidth?: number;\n contentHeight?: number;\n panBoundaryPadding?: number;\n maxZoom?: number;\n minZoom?: number;\n doubleTapDelay?: number;\n doubleTapZoomToCenter?: boolean;\n bindToBorders?: boolean;\n zoomStep?: number;\n pinchToZoomInSensitivity?: number;\n pinchToZoomOutSensitivity?: number;\n movementSensibility?: number;\n longPressDuration?: number;\n visualTouchFeedbackEnabled?: boolean;\n disablePanOnInitialZoom?: boolean;\n\n // Zoom animated value ref\n zoomAnimatedValue?: Animated.Value;\n panAnimatedValueXY?: Animated.ValueXY;\n\n // debug\n debug?: boolean;\n\n // callbacks\n onTransform?: (zoomableViewEventObject: ZoomableViewEvent) => void;\n onSingleTap?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapBefore?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapAfter?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onShiftingBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean | undefined;\n onZoomAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onLongPress?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onStartShouldSetPanResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent,\n baseComponentResult: boolean\n ) => boolean;\n onPanResponderGrant?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderMove?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onPanResponderTerminate?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderTerminationRequest?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShouldBlockNativeResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onStartShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onMoveShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onStaticPinPress?: (event: GestureResponderEvent) => void;\n onStaticPinLongPress?: (event: GestureResponderEvent) => void;\n staticPinPosition?: Vec2D;\n staticPinIcon?: React.ReactElement;\n onStaticPinPositionChange?: (position: Vec2D) => void;\n onStaticPinPositionMove?: (position: Vec2D) => void;\n animatePin: boolean;\n pinProps?: ViewProps;\n disableMomentum?: boolean;\n}\n\nexport interface Vec2D {\n x: number;\n y: number;\n}\n\nexport interface Size2D {\n width: number;\n height: number;\n}\n\nexport interface TouchPoint extends Vec2D {\n id: string;\n isSecondTap?: boolean;\n}\n\nexport interface ReactNativeZoomableViewState {\n touches?: TouchPoint[];\n originalWidth: number | null;\n originalHeight: number | null;\n originalPageX: number | null;\n originalPageY: number | null;\n debugPoints?: undefined | Vec2D[];\n pinSize: Size2D;\n}\n\nexport interface ReactNativeZoomableViewWithGesturesProps\n extends ReactNativeZoomableViewProps {\n swipeLengthThreshold?: number;\n swipeVelocityThreshold?: number;\n swipeDirectionalThreshold?: number;\n swipeMinZoom?: number;\n swipeMaxZoom?: number;\n swipeDisabled?: boolean;\n onSwipe?: (\n swipeDirection: SwipeDirection,\n gestureState: PanResponderGestureState\n ) => void;\n onSwipeUp?: (gestureState: PanResponderGestureState) => void;\n onSwipeDown?: (gestureState: PanResponderGestureState) => void;\n onSwipeLeft?: (gestureState: PanResponderGestureState) => void;\n onSwipeRight?: (gestureState: PanResponderGestureState) => void;\n}\n"]} \ No newline at end of file +{"version":3,"sources":["index.ts"],"names":["SwipeDirection"],"mappings":";;;;;;IAOYA,c;;;WAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;GAAAA,c,8BAAAA,c","sourcesContent":["import {\n Animated,\n GestureResponderEvent,\n PanResponderGestureState,\n ViewProps,\n} from 'react-native';\n\nexport enum SwipeDirection {\n SWIPE_UP = 'SWIPE_UP',\n SWIPE_DOWN = 'SWIPE_DOWN',\n SWIPE_LEFT = 'SWIPE_LEFT',\n SWIPE_RIGHT = 'SWIPE_RIGHT',\n}\n\nexport interface ZoomableViewEvent {\n zoomLevel: number;\n offsetX: number;\n offsetY: number;\n originalHeight: number;\n originalWidth: number;\n originalPageX: number;\n originalPageY: number;\n}\n\nexport interface ReactNativeZoomableViewProps extends ViewProps {\n // options\n zoomEnabled?: boolean;\n panEnabled?: boolean;\n initialZoom?: number;\n initialOffsetX?: number;\n initialOffsetY?: number;\n contentWidth?: number;\n contentHeight?: number;\n panBoundaryPadding?: number;\n maxZoom?: number;\n minZoom?: number;\n doubleTapDelay?: number;\n doubleTapZoomToCenter?: boolean;\n bindToBorders?: boolean;\n zoomStep?: number;\n pinchToZoomInSensitivity?: number;\n pinchToZoomOutSensitivity?: number;\n movementSensibility?: number;\n longPressDuration?: number;\n visualTouchFeedbackEnabled?: boolean;\n disablePanOnInitialZoom?: boolean;\n\n // Zoom animated value ref\n zoomAnimatedValue?: Animated.Value;\n panAnimatedValueXY?: Animated.ValueXY;\n\n // debug\n debug?: boolean;\n\n // callbacks\n onTransform?: (zoomableViewEventObject: ZoomableViewEvent) => void;\n onSingleTap?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapBefore?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapAfter?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onShiftingBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean | undefined;\n onZoomAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onLongPress?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onStartShouldSetPanResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent,\n baseComponentResult: boolean\n ) => boolean;\n onPanResponderGrant?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderMove?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onPanResponderTerminate?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderTerminationRequest?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShouldBlockNativeResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onStartShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onMoveShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onStaticPinPress?: (event: GestureResponderEvent) => void;\n onStaticPinLongPress?: (event: GestureResponderEvent) => void;\n staticPinPosition?: Vec2D;\n staticPinIcon?: React.ReactElement;\n onStaticPinPositionChange?: (position: Vec2D) => void;\n onStaticPinPositionMove?: (position: Vec2D) => void;\n animatePin: boolean;\n pinProps?: ViewProps;\n disableMomentum?: boolean;\n}\n\nexport interface Vec2D {\n x: number;\n y: number;\n}\n\nexport interface Size2D {\n width: number;\n height: number;\n}\n\nexport interface TouchPoint extends Vec2D {\n id: string;\n isSecondTap?: boolean;\n}\n\nexport interface ReactNativeZoomableViewState {\n touches?: TouchPoint[];\n originalWidth: number;\n originalHeight: number;\n originalPageX: number;\n originalPageY: number;\n debugPoints?: undefined | Vec2D[];\n pinSize: Size2D;\n}\n\nexport interface ReactNativeZoomableViewWithGesturesProps\n extends ReactNativeZoomableViewProps {\n swipeLengthThreshold?: number;\n swipeVelocityThreshold?: number;\n swipeDirectionalThreshold?: number;\n swipeMinZoom?: number;\n swipeMaxZoom?: number;\n swipeDisabled?: boolean;\n onSwipe?: (\n swipeDirection: SwipeDirection,\n gestureState: PanResponderGestureState\n ) => void;\n onSwipeUp?: (gestureState: PanResponderGestureState) => void;\n onSwipeDown?: (gestureState: PanResponderGestureState) => void;\n onSwipeLeft?: (gestureState: PanResponderGestureState) => void;\n onSwipeRight?: (gestureState: PanResponderGestureState) => void;\n}\n"]} \ No newline at end of file diff --git a/lib/module/ReactNativeZoomableView.js b/lib/module/ReactNativeZoomableView.js index 9dd4b0d..98cf780 100644 --- a/lib/module/ReactNativeZoomableView.js +++ b/lib/module/ReactNativeZoomableView.js @@ -13,10 +13,10 @@ import { StaticPin } from './components/StaticPin'; import { debounce } from 'lodash'; import { getBoundaryCrossedAnim, getPanMomentumDecayAnim, getZoomToAnimation } from './animations'; const initialState = { - originalWidth: null, - originalHeight: null, - originalPageX: null, - originalPageY: null, + originalWidth: 0, + originalHeight: 0, + originalPageX: 0, + originalPageY: 0, pinSize: { width: 0, height: 0 @@ -284,7 +284,7 @@ class ReactNativeZoomableView extends Component { delete this.doubleTapFirstTap; this._handleDoubleTap(e); - } else if (this.state.originalPageX && this.state.originalPageY) { + } else { this.doubleTapFirstTapReleaseTimestamp = now; this.doubleTapFirstTap = { id: now.toString(), @@ -322,7 +322,7 @@ class ReactNativeZoomableView extends Component { } }); - _defineProperty(this, "moveStaticPinTo", position => { + _defineProperty(this, "moveStaticPinTo", (position, duration) => { const { originalWidth, originalHeight @@ -340,10 +340,22 @@ class ReactNativeZoomableView extends Component { const pinY = staticPinPosition.y - originalHeight / 2; this.offsetX = contentWidth / 2 - position.x + pinX / this.zoomLevel; this.offsetY = contentHeight / 2 - position.y + pinY / this.zoomLevel; - this.panAnim.setValue({ - x: this.offsetX, - y: this.offsetY - }); + + if (duration) { + Animated.timing(this.panAnim, { + toValue: { + x: this.offsetX, + y: this.offsetY + }, + useNativeDriver: true, + duration + }).start(); + } else { + this.panAnim.setValue({ + x: this.offsetX, + y: this.offsetY + }); + } }); _defineProperty(this, "_staticPinPosition", () => { @@ -660,8 +672,6 @@ class ReactNativeZoomableView extends Component { const gestureCenterPoint = calcGestureCenterPoint(e, gestureState); if (!gestureCenterPoint) return; - if (this.state.originalPageX == null) return; - if (this.state.originalPageY == null) return; let zoomCenter = { x: gestureCenterPoint.x - this.state.originalPageX, y: gestureCenterPoint.y - this.state.originalPageY @@ -723,8 +733,6 @@ class ReactNativeZoomableView extends Component { originalPageY, originalPageX } = this.state; - if (originalPageX == null) return; - if (originalPageY == null) return; this.setState({ debugPoints: [{ x: touches[0].pageX - originalPageX, @@ -877,9 +885,7 @@ class ReactNativeZoomableView extends Component { const { originalPageX, originalPageY - } = this.state; - if (originalPageX == null) return; - if (originalPageY == null) return; // define new zoom position coordinates + } = this.state; // define new zoom position coordinates const zoomPositionCoordinates = { x: e.nativeEvent.pageX - originalPageX, @@ -944,8 +950,6 @@ class ReactNativeZoomableView extends Component { var _this$props$onZoomBef, _this$props17, _this$props$onZoomAft2, _this$props18; if (!this.props.zoomEnabled) return; - if (this.state.originalWidth == null) return; - if (this.state.originalHeight == null) return; (_this$props$onZoomBef = (_this$props17 = this.props).onZoomBefore) === null || _this$props$onZoomBef === void 0 ? void 0 : _this$props$onZoomBef.call(_this$props17, null, null, this._getZoomableViewEventObject()); // == Perform Zoom Animation == // Calculates panAnim values based on changes in zoomAnim. @@ -957,8 +961,6 @@ class ReactNativeZoomableView extends Component { const listenerId = this.zoomAnim.addListener(({ value: newScale }) => { - if (this.state.originalWidth == null) return; - if (this.state.originalHeight == null) return; this.panAnim.setValue({ x: calcNewScaledOffsetForZoomCentering(this.offsetX, this.state.originalWidth, prevScale, newScale, x), y: calcNewScaledOffsetForZoomCentering(this.offsetY, this.state.originalHeight, prevScale, newScale, y) diff --git a/lib/module/ReactNativeZoomableView.js.map b/lib/module/ReactNativeZoomableView.js.map index eb60fb0..d98af8e 100644 --- a/lib/module/ReactNativeZoomableView.js.map +++ b/lib/module/ReactNativeZoomableView.js.map @@ -1 +1 @@ -{"version":3,"sources":["ReactNativeZoomableView.tsx"],"names":["React","Component","createRef","Animated","Easing","PanResponder","StyleSheet","View","AnimatedTouchFeedback","DebugTouchPoint","calcGestureCenterPoint","calcGestureTouchDistance","calcNewScaledOffsetForZoomCentering","applyPanBoundariesToOffset","viewportPositionToImagePosition","StaticPin","debounce","getBoundaryCrossedAnim","getPanMomentumDecayAnim","getZoomToAnimation","initialState","originalWidth","originalHeight","originalPageX","originalPageY","pinSize","width","height","ReactNativeZoomableView","gestureStarted","v","_gestureStarted","constructor","props","ValueXY","x","y","Value","value","boundaryCrossedAnimInEffect","position","onStaticPinPositionChange","requestAnimationFrame","setTimeout","zoomSubjectWrapperRef","current","measureInWindow","setState","e","gestureState","onStartShouldSetPanResponder","_getZoomableViewEventObject","onLongPress","longPressTimeout","longPressDuration","onPanResponderGrant","panAnim","stopAnimation","zoomAnim","raisePin","gestureType","_resolveAndHandleTap","debugPoints","lastGestureCenterPosition","disableMomentum","panEnabled","disablePanOnInitialZoom","zoomLevel","initialZoom","vx","vy","start","clearTimeout","onPanResponderEnd","onZoomEnd","onShiftingEnd","staticPinPosition","_updateStaticPin","dropPin","onPanResponderMove","numberActiveTouches","_handlePanResponderGrant","_handlePanResponderEnd","lastGestureTouchDistance","_handlePinching","Math","abs","dx","dy","isShiftGesture","_handleShifting","now","Date","doubleTapFirstTapReleaseTimestamp","doubleTapDelay","doubleTapFirstTap","_addTouch","id","toString","isSecondTap","singleTapTimeoutId","_handleDoubleTap","state","nativeEvent","pageX","pageY","persist","tapX","tapY","timing","toValue","offsetX","offsetY","useNativeDriver","duration","onSingleTap","contentWidth","contentHeight","pinX","pinY","setValue","viewportPosition","imageSize","zoomableEvent","_staticPinPosition","gestureHandlers","create","_handleStartShouldSetPanResponder","_handlePanResponderMove","onPanResponderRelease","onPanResponderTerminate","evt","onPanResponderTerminationRequest","onShouldBlockNativeResponder","onStartShouldSetPanResponderCapture","onMoveShouldSetPanResponderCapture","zoomAnimatedValue","panAnimatedValueXY","initialOffsetX","initialOffsetY","addListener","animatePin","pinAnim","easing","out","ease","__setOffset","__getOffset","axis","offset","offsetState","__offsets","bindToBorders","containerSize","contentSize","boundOffset","panBoundaryPadding","boundariesApplied","toFixed","componentDidUpdate","prevProps","prevState","zoomEnabled","onTransformInvocationInitialized","_invokeOnTransform","successful","currState","originalMeasurementsChanged","staticPinPositionChanged","componentDidMount","grabZoomSubjectOriginalMeasurements","measureZoomSubjectInterval","setInterval","componentWillUnmount","clearInterval","zoomableViewEvent","onTransform","onStaticPinPositionMove","debouncedOnStaticPinPositionChange","overwriteObj","maxZoom","minZoom","pinchToZoomInSensitivity","pinchToZoomOutSensitivity","distance","onZoomBefore","zoomGrowthFromLastGestureState","pinchToZoomSensitivity","deltaGrowth","deltaGrowthAdjustedBySensitivity","newZoomLevel","gestureCenterPoint","zoomCenter","debug","_setPinchDebugPoints","oldOffsetX","oldOffsetY","oldScale","newScale","offsetShift","_calcOffsetShiftSinceLastGestureState","onZoomAfter","gestureResponderEvent","points","touches","movementSensibility","shift","shiftX","shiftY","moveX","moveY","_setNewOffsetPosition","newOffsetX","newOffsetY","onShiftingBefore","onShiftingAfter","touch","push","_removeTouch","splice","indexOf","onDoubleTapBefore","onDoubleTapAfter","doubleTapZoomToCenter","nextZoomStep","_getNextZoomStep","zoomPositionCoordinates","_zoomToLocation","zoomStep","prevScale","listenerId","removeListener","zoomTo","zoomBy","zoomLevelChange","moveTo","moveBy","offsetChangeX","offsetChangeY","render","staticPinIcon","children","visualTouchFeedbackEnabled","onStaticPinLongPress","onStaticPinPress","pinProps","styles","container","panHandlers","zoomSubject","style","transform","scale","getTranslateTransform","map","index","size","undefined","alignItems","flex","justifyContent","overflow"],"mappings":"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","sourcesContent":["import React, { Component, createRef, RefObject } from 'react';\nimport {\n Animated,\n Easing,\n GestureResponderEvent,\n PanResponder,\n PanResponderCallbacks,\n PanResponderGestureState,\n PanResponderInstance,\n StyleSheet,\n View,\n} from 'react-native';\n\nimport {\n Vec2D,\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState,\n TouchPoint,\n ZoomableViewEvent,\n Size2D,\n} from './typings';\n\nimport { AnimatedTouchFeedback } from './components';\nimport { DebugTouchPoint } from './debugHelper';\nimport {\n calcGestureCenterPoint,\n calcGestureTouchDistance,\n calcNewScaledOffsetForZoomCentering,\n} from './helper';\nimport { applyPanBoundariesToOffset } from './helper/applyPanBoundariesToOffset';\nimport { viewportPositionToImagePosition } from './helper/coordinateConversion';\nimport { StaticPin } from './components/StaticPin';\nimport { debounce } from 'lodash';\nimport {\n getBoundaryCrossedAnim,\n getPanMomentumDecayAnim,\n getZoomToAnimation,\n} from './animations';\n\nconst initialState: ReactNativeZoomableViewState = {\n originalWidth: null,\n originalHeight: null,\n originalPageX: null,\n originalPageY: null,\n pinSize: { width: 0, height: 0 },\n};\n\nclass ReactNativeZoomableView extends Component<\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState\n> {\n zoomSubjectWrapperRef: RefObject;\n gestureHandlers: PanResponderInstance;\n doubleTapFirstTapReleaseTimestamp: number | undefined;\n\n static defaultProps = {\n zoomEnabled: true,\n panEnabled: true,\n initialZoom: 1,\n initialOffsetX: 0,\n initialOffsetY: 0,\n maxZoom: 1.5,\n minZoom: 0.5,\n pinchToZoomInSensitivity: 1,\n pinchToZoomOutSensitivity: 1,\n movementSensibility: 1,\n doubleTapDelay: 300,\n bindToBorders: true,\n zoomStep: 0.5,\n onLongPress: null,\n longPressDuration: 700,\n contentWidth: undefined,\n contentHeight: undefined,\n panBoundaryPadding: 0,\n visualTouchFeedbackEnabled: true,\n staticPinPosition: undefined,\n staticPinIcon: undefined,\n onStaticPinPositionChange: undefined,\n onStaticPinPositionMove: undefined,\n animatePin: true,\n disablePanOnInitialZoom: false,\n };\n\n private panAnim = new Animated.ValueXY({ x: 0, y: 0 });\n private zoomAnim = new Animated.Value(1);\n private pinAnim = new Animated.ValueXY({ x: 0, y: 0 });\n\n private __offsets = {\n x: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n y: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n };\n\n private zoomLevel = 1;\n private lastGestureCenterPosition: { x: number; y: number } | null = null;\n private lastGestureTouchDistance: number | null = null;\n private gestureType: 'pinch' | 'shift' | null;\n\n private _gestureStarted = false;\n private set gestureStarted(v: boolean) {\n this._gestureStarted = v;\n }\n\n public get gestureStarted() {\n return this._gestureStarted;\n }\n\n /**\n * Last press time (used to evaluate whether user double tapped)\n * @type {number}\n */\n private longPressTimeout: NodeJS.Timeout | null = null;\n private onTransformInvocationInitialized: boolean | undefined;\n private singleTapTimeoutId: NodeJS.Timeout | undefined;\n private touches: TouchPoint[] = [];\n private doubleTapFirstTap: TouchPoint | undefined;\n private measureZoomSubjectInterval: NodeJS.Timer | undefined;\n\n constructor(props: ReactNativeZoomableViewProps) {\n super(props);\n // This needs to be done before anything else to initialize the state.\n // Otherwise, the logic below may reference the state when it's undefined,\n // causing runtime errors.\n this.state = { ...initialState };\n\n this.gestureHandlers = PanResponder.create({\n onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,\n onPanResponderGrant: this._handlePanResponderGrant,\n onPanResponderMove: this._handlePanResponderMove,\n onPanResponderRelease: this._handlePanResponderEnd,\n onPanResponderTerminate: (evt, gestureState) => {\n // We should also call _handlePanResponderEnd\n // to properly perform cleanups when the gesture is terminated\n // (aka gesture handling responsibility is taken over by another component).\n // This also fixes a weird issue where\n // on real device, sometimes onPanResponderRelease is not called when you lift 2 fingers up,\n // but onPanResponderTerminate is called instead for no apparent reason.\n this._handlePanResponderEnd(evt, gestureState);\n this.props.onPanResponderTerminate?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n );\n },\n onPanResponderTerminationRequest: (evt, gestureState) =>\n !!this.props.onPanResponderTerminationRequest?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ),\n // Defaults to true to prevent parent components, such as React Navigation's tab view, from taking over as responder.\n onShouldBlockNativeResponder: (evt, gestureState) =>\n this.props.onShouldBlockNativeResponder?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ) ?? true,\n onStartShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onStartShouldSetPanResponderCapture?.(evt, gestureState),\n onMoveShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onMoveShouldSetPanResponderCapture?.(evt, gestureState),\n });\n\n this.zoomSubjectWrapperRef = createRef();\n\n if (this.props.zoomAnimatedValue)\n this.zoomAnim = this.props.zoomAnimatedValue;\n if (this.props.panAnimatedValueXY)\n this.panAnim = this.props.panAnimatedValueXY;\n\n if (this.props.initialZoom) this.zoomLevel = this.props.initialZoom;\n if (this.props.initialOffsetX != null)\n this.offsetX = this.props.initialOffsetX;\n if (this.props.initialOffsetY != null)\n this.offsetY = this.props.initialOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n this.panAnim.addListener(({ x, y }) => {\n this.offsetX = x;\n this.offsetY = y;\n });\n this.zoomAnim.addListener(({ value }) => {\n this.zoomLevel = value;\n });\n\n this.lastGestureTouchDistance = 150;\n\n this.gestureType = null;\n }\n\n private raisePin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: -10 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private dropPin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: 0 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private set offsetX(x: number) {\n this.__setOffset('x', x);\n }\n\n private set offsetY(y: number) {\n this.__setOffset('y', y);\n }\n\n private get offsetX() {\n return this.__getOffset('x');\n }\n\n private get offsetY() {\n return this.__getOffset('y');\n }\n\n private __setOffset(axis: 'x' | 'y', offset: number) {\n const offsetState = this.__offsets[axis];\n\n if (this.props.bindToBorders) {\n const containerSize =\n axis === 'x' ? this.state.originalWidth : this.state.originalHeight;\n const contentSize =\n axis === 'x'\n ? this.props.contentWidth || this.state.originalWidth\n : this.props.contentHeight || this.state.originalHeight;\n\n const boundOffset =\n contentSize && containerSize && this.props.panBoundaryPadding != null\n ? applyPanBoundariesToOffset(\n offset,\n containerSize,\n contentSize,\n this.zoomLevel,\n this.props.panBoundaryPadding\n )\n : offset;\n\n if (!this.gestureType && !offsetState.boundaryCrossedAnimInEffect) {\n const boundariesApplied =\n boundOffset !== offset &&\n boundOffset.toFixed(3) !== offset.toFixed(3);\n if (boundariesApplied) {\n offsetState.boundaryCrossedAnimInEffect = true;\n getBoundaryCrossedAnim(this.panAnim[axis], boundOffset).start(() => {\n offsetState.boundaryCrossedAnimInEffect = false;\n });\n return;\n }\n }\n }\n\n offsetState.value = offset;\n }\n\n private __getOffset(axis: 'x' | 'y') {\n return this.__offsets[axis].value;\n }\n\n componentDidUpdate(\n prevProps: ReactNativeZoomableViewProps,\n prevState: ReactNativeZoomableViewState\n ) {\n const { zoomEnabled, initialZoom } = this.props;\n if (prevProps.zoomEnabled && !zoomEnabled && initialZoom) {\n this.zoomLevel = initialZoom;\n this.zoomAnim.setValue(this.zoomLevel);\n }\n if (\n !this.onTransformInvocationInitialized &&\n this._invokeOnTransform().successful\n ) {\n this.panAnim.addListener(() => this._invokeOnTransform());\n this.zoomAnim.addListener(() => this._invokeOnTransform());\n this.onTransformInvocationInitialized = true;\n }\n\n const currState = this.state;\n const originalMeasurementsChanged =\n currState.originalHeight !== prevState.originalHeight ||\n currState.originalWidth !== prevState.originalWidth ||\n currState.originalPageX !== prevState.originalPageX ||\n currState.originalPageY !== prevState.originalPageY;\n\n const staticPinPositionChanged =\n prevProps.staticPinPosition?.x !== this.props.staticPinPosition?.x ||\n prevProps.staticPinPosition?.y !== this.props.staticPinPosition?.y;\n\n if (\n this.onTransformInvocationInitialized &&\n (originalMeasurementsChanged || staticPinPositionChanged)\n ) {\n this._invokeOnTransform();\n }\n }\n\n componentDidMount() {\n this.grabZoomSubjectOriginalMeasurements();\n // We've already run `grabZoomSubjectOriginalMeasurements` at various events\n // to make sure the measurements are promptly updated.\n // However, there might be cases we haven't accounted for, especially when\n // native processes are involved. To account for those cases,\n // we'll use an interval here to ensure we're always up-to-date.\n // The `setState` in `grabZoomSubjectOriginalMeasurements` won't trigger a rerender\n // if the values given haven't changed, so we're not running performance risk here.\n this.measureZoomSubjectInterval = setInterval(\n this.grabZoomSubjectOriginalMeasurements,\n 1e3\n );\n }\n\n componentWillUnmount() {\n this.measureZoomSubjectInterval &&\n clearInterval(this.measureZoomSubjectInterval);\n }\n\n debouncedOnStaticPinPositionChange = debounce(\n (position: Vec2D) => this.props.onStaticPinPositionChange?.(position),\n 100\n );\n\n /**\n * try to invoke onTransform\n * @private\n */\n _invokeOnTransform() {\n const zoomableViewEvent = this._getZoomableViewEventObject();\n const position = this._staticPinPosition();\n\n if (!zoomableViewEvent.originalWidth || !zoomableViewEvent.originalHeight)\n return { successful: false };\n\n this.props.onTransform?.(zoomableViewEvent);\n\n if (position) {\n this.props.onStaticPinPositionMove?.(position);\n this.debouncedOnStaticPinPositionChange(position);\n }\n\n return { successful: true };\n }\n\n /**\n * Returns additional information about components current state for external event hooks\n *\n * @returns {{}}\n * @private\n */\n _getZoomableViewEventObject(overwriteObj = {}): ZoomableViewEvent {\n return {\n zoomLevel: this.zoomLevel,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n originalHeight: this.state.originalHeight,\n originalWidth: this.state.originalWidth,\n originalPageX: this.state.originalPageX,\n originalPageY: this.state.originalPageY,\n ...overwriteObj,\n } as ZoomableViewEvent;\n }\n\n /**\n * Get the original box dimensions and save them for later use.\n * (They will be used to calculate boxBorders)\n *\n * @private\n */\n private grabZoomSubjectOriginalMeasurements = () => {\n // make sure we measure after animations are complete\n requestAnimationFrame(() => {\n // this setTimeout is here to fix a weird issue on iOS where the measurements are all `0`\n // when navigating back (react-navigation stack) from another view\n // while closing the keyboard at the same time\n setTimeout(() => {\n // In normal conditions, we're supposed to measure zoomSubject instead of its wrapper.\n // However, our zoomSubject may have been transformed by an initial zoomLevel or offset,\n // in which case these measurements will not represent the true \"original\" measurements.\n // We just need to make sure the zoomSubjectWrapper perfectly aligns with the zoomSubject\n // (no border, space, or anything between them)\n const zoomSubjectWrapperRef = this.zoomSubjectWrapperRef;\n // we don't wanna measure when zoomSubjectWrapperRef is not yet available or has been unmounted\n zoomSubjectWrapperRef.current?.measureInWindow(\n (x, y, width, height) => {\n // When the component is off-screen, these become all 0s, so we don't set them\n // to avoid messing up calculations, especially ones that are done right after\n // the component transitions from hidden to visible.\n if (!x && !y && !width && !height) return;\n this.setState({\n originalWidth: width,\n originalHeight: height,\n originalPageX: x,\n originalPageY: y,\n });\n }\n );\n });\n });\n };\n\n /**\n * Handles the start of touch events and checks for taps\n *\n * @param e\n * @param gestureState\n * @returns {boolean}\n *\n * @private\n */\n _handleStartShouldSetPanResponder = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onStartShouldSetPanResponder) {\n this.props.onStartShouldSetPanResponder(\n e,\n gestureState,\n this._getZoomableViewEventObject(),\n false\n );\n }\n\n // Always set pan responder on start\n // of gesture so we can handle tap.\n // \"Pan threshold validation\" will be handled\n // in `onPanResponderMove` instead of in `onMoveShouldSetPanResponder`\n return true;\n };\n\n /**\n * Calculates pinch distance\n *\n * @param e\n * @param gestureState\n * @private\n */\n _handlePanResponderGrant: NonNullable<\n PanResponderCallbacks['onPanResponderGrant']\n > = (e, gestureState) => {\n if (this.props.onLongPress) {\n this.longPressTimeout = setTimeout(() => {\n this.props.onLongPress?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n this.longPressTimeout = null;\n }, this.props.longPressDuration);\n }\n\n this.props.onPanResponderGrant?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n this.panAnim.stopAnimation();\n this.zoomAnim.stopAnimation();\n this.gestureStarted = true;\n\n this.raisePin();\n };\n\n /**\n * Handles the end of touch events\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderEnd: NonNullable<\n PanResponderCallbacks['onPanResponderEnd']\n > = (e, gestureState) => {\n if (!this.gestureType) {\n this._resolveAndHandleTap(e);\n }\n\n this.setState({ debugPoints: [] });\n\n this.lastGestureCenterPosition = null;\n\n const disableMomentum =\n this.props.disableMomentum ||\n (this.props.panEnabled &&\n this.gestureType === 'shift' &&\n this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom);\n\n // Trigger final shift animation unless disablePanOnInitialZoom is set and we're on the initial zoom level\n // or disableMomentum\n if (!disableMomentum) {\n getPanMomentumDecayAnim(this.panAnim, {\n x: gestureState.vx / this.zoomLevel,\n y: gestureState.vy / this.zoomLevel,\n }).start();\n }\n\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n this.props.onPanResponderEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n if (this.gestureType === 'pinch') {\n this.props.onZoomEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n } else if (this.gestureType === 'shift') {\n this.props.onShiftingEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n if (this.props.staticPinPosition) {\n this._updateStaticPin();\n }\n\n this.dropPin();\n\n this.gestureType = null;\n this.gestureStarted = false;\n };\n\n /**\n * Handles the actual movement of our pan responder\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderMove = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onPanResponderMove) {\n if (\n this.props.onPanResponderMove(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return false;\n }\n }\n\n // Only supports 2 touches and below,\n // any invalid number will cause the gesture to end.\n if (gestureState.numberActiveTouches <= 2) {\n if (!this.gestureStarted) {\n this._handlePanResponderGrant(e, gestureState);\n }\n } else {\n if (this.gestureStarted) {\n this._handlePanResponderEnd(e, gestureState);\n }\n return true;\n }\n\n if (gestureState.numberActiveTouches === 2) {\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'pinch') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n this.lastGestureTouchDistance = calcGestureTouchDistance(\n e,\n gestureState\n );\n }\n this.gestureType = 'pinch';\n this._handlePinching(e, gestureState);\n } else if (gestureState.numberActiveTouches === 1) {\n if (\n this.longPressTimeout &&\n (Math.abs(gestureState.dx) > 5 || Math.abs(gestureState.dy) > 5)\n ) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'shift') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n }\n\n const { dx, dy } = gestureState;\n const isShiftGesture = Math.abs(dx) > 2 || Math.abs(dy) > 2;\n if (isShiftGesture) {\n this.gestureType = 'shift';\n this._handleShifting(gestureState);\n }\n }\n };\n\n /**\n * Handles the pinch movement and zooming\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePinching(\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) {\n if (!this.props.zoomEnabled) return;\n\n const {\n maxZoom,\n minZoom,\n pinchToZoomInSensitivity,\n pinchToZoomOutSensitivity,\n } = this.props;\n\n const distance = calcGestureTouchDistance(e, gestureState);\n\n if (\n this.props.onZoomBefore &&\n this.props.onZoomBefore(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return;\n }\n\n if (!distance) return;\n if (!this.lastGestureTouchDistance) return;\n\n // define the new zoom level and take zoom level sensitivity into consideration\n const zoomGrowthFromLastGestureState =\n distance / this.lastGestureTouchDistance;\n this.lastGestureTouchDistance = distance;\n\n const pinchToZoomSensitivity =\n zoomGrowthFromLastGestureState < 1\n ? pinchToZoomOutSensitivity\n : pinchToZoomInSensitivity;\n\n if (pinchToZoomSensitivity == null) return;\n const deltaGrowth = zoomGrowthFromLastGestureState - 1;\n // 0 - no resistance\n // 10 - 90% resistance\n const deltaGrowthAdjustedBySensitivity =\n deltaGrowth * (1 - (pinchToZoomSensitivity * 9) / 100);\n\n let newZoomLevel = this.zoomLevel * (1 + deltaGrowthAdjustedBySensitivity);\n\n // make sure max and min zoom levels are respected\n if (maxZoom != null && newZoomLevel > maxZoom) {\n newZoomLevel = maxZoom;\n }\n\n if (minZoom != null && newZoomLevel < minZoom) {\n newZoomLevel = minZoom;\n }\n\n const gestureCenterPoint = calcGestureCenterPoint(e, gestureState);\n\n if (!gestureCenterPoint) return;\n if (this.state.originalPageX == null) return;\n if (this.state.originalPageY == null) return;\n\n let zoomCenter = {\n x: gestureCenterPoint.x - this.state.originalPageX,\n y: gestureCenterPoint.y - this.state.originalPageY,\n };\n\n if (this.props.staticPinPosition) {\n // When we use a static pin position, the zoom centre is the same as that position,\n // otherwise the pin moves around way too much while zooming.\n zoomCenter = {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n };\n }\n\n // Uncomment to debug\n this.props.debug && this._setPinchDebugPoints(e, zoomCenter);\n\n const { originalHeight, originalWidth } = this.state;\n\n const oldOffsetX = this.offsetX;\n const oldOffsetY = this.offsetY;\n const oldScale = this.zoomLevel;\n const newScale = newZoomLevel;\n\n if (!originalHeight || !originalWidth) return;\n\n let offsetY = calcNewScaledOffsetForZoomCentering(\n oldOffsetY,\n originalHeight,\n oldScale,\n newScale,\n zoomCenter.y\n );\n let offsetX = calcNewScaledOffsetForZoomCentering(\n oldOffsetX,\n originalWidth,\n oldScale,\n newScale,\n zoomCenter.x\n );\n\n const offsetShift =\n this._calcOffsetShiftSinceLastGestureState(gestureCenterPoint);\n if (offsetShift) {\n offsetX += offsetShift.x;\n offsetY += offsetShift.y;\n }\n\n this.offsetX = offsetX;\n this.offsetY = offsetY;\n this.zoomLevel = newScale;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n this.props.onZoomAfter?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n /**\n * Used to debug pinch events\n * @param gestureResponderEvent\n * @param zoomCenter\n * @param points\n */\n _setPinchDebugPoints(\n gestureResponderEvent: GestureResponderEvent,\n zoomCenter: Vec2D,\n ...points: Vec2D[]\n ) {\n const { touches } = gestureResponderEvent.nativeEvent;\n const { originalPageY, originalPageX } = this.state;\n if (originalPageX == null) return;\n if (originalPageY == null) return;\n\n this.setState({\n debugPoints: [\n {\n x: touches[0].pageX - originalPageX,\n y: touches[0].pageY - originalPageY,\n },\n {\n x: touches[1].pageX - originalPageX,\n y: touches[1].pageY - originalPageY,\n },\n zoomCenter,\n ...points,\n ],\n });\n }\n\n /**\n * Calculates the amount the offset should shift since the last position during panning\n *\n * @param {Vec2D} gestureCenterPoint\n *\n * @private\n */\n _calcOffsetShiftSinceLastGestureState(gestureCenterPoint: Vec2D) {\n const { movementSensibility } = this.props;\n\n let shift = null;\n\n if (this.lastGestureCenterPosition && movementSensibility) {\n const dx = gestureCenterPoint.x - this.lastGestureCenterPosition.x;\n const dy = gestureCenterPoint.y - this.lastGestureCenterPosition.y;\n\n const shiftX = dx / this.zoomLevel / movementSensibility;\n const shiftY = dy / this.zoomLevel / movementSensibility;\n\n shift = {\n x: shiftX,\n y: shiftY,\n };\n }\n\n this.lastGestureCenterPosition = gestureCenterPoint;\n\n return shift;\n }\n\n /**\n * Handles movement by tap and move\n *\n * @param gestureState\n *\n * @private\n */\n _handleShifting(gestureState: PanResponderGestureState) {\n // Skips shifting if panEnabled is false or disablePanOnInitialZoom is true and we're on the initial zoom level\n if (\n !this.props.panEnabled ||\n (this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom)\n ) {\n return;\n }\n const shift = this._calcOffsetShiftSinceLastGestureState({\n x: gestureState.moveX,\n y: gestureState.moveY,\n });\n if (!shift) return;\n\n const offsetX = this.offsetX + shift.x;\n const offsetY = this.offsetY + shift.y;\n\n if (\n this.props.debug &&\n this.state.originalPageX &&\n this.state.originalPageY\n ) {\n const x = gestureState.moveX - this.state.originalPageX;\n const y = gestureState.moveY - this.state.originalPageY;\n this.setState({ debugPoints: [{ x, y }] });\n }\n\n this._setNewOffsetPosition(offsetX, offsetY);\n\n this.raisePin();\n }\n\n /**\n * Set the state to offset moved\n *\n * @param {number} newOffsetX\n * @param {number} newOffsetY\n * @returns\n */\n _setNewOffsetPosition(newOffsetX: number, newOffsetY: number) {\n const { onShiftingBefore, onShiftingAfter } = this.props;\n\n if (onShiftingBefore?.(null, null, this._getZoomableViewEventObject())) {\n return;\n }\n\n this.offsetX = newOffsetX;\n this.offsetY = newOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n onShiftingAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Check whether the press event is double tap\n * or single tap and handle the event accordingly\n *\n * @param e\n *\n * @private\n */\n private _resolveAndHandleTap = (e: GestureResponderEvent) => {\n const now = Date.now();\n if (\n this.doubleTapFirstTapReleaseTimestamp &&\n this.props.doubleTapDelay &&\n now - this.doubleTapFirstTapReleaseTimestamp < this.props.doubleTapDelay\n ) {\n this.doubleTapFirstTap &&\n this._addTouch({\n ...this.doubleTapFirstTap,\n id: now.toString(),\n isSecondTap: true,\n });\n this.singleTapTimeoutId && clearTimeout(this.singleTapTimeoutId);\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n delete this.doubleTapFirstTap;\n this._handleDoubleTap(e);\n } else if (this.state.originalPageX && this.state.originalPageY) {\n this.doubleTapFirstTapReleaseTimestamp = now;\n this.doubleTapFirstTap = {\n id: now.toString(),\n x: e.nativeEvent.pageX - this.state.originalPageX,\n y: e.nativeEvent.pageY - this.state.originalPageY,\n };\n this._addTouch(this.doubleTapFirstTap);\n\n // persist event so e.nativeEvent is preserved after a timeout delay\n e.persist();\n this.singleTapTimeoutId = setTimeout(() => {\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n\n // Pan to the tapped location\n if (this.props.staticPinPosition && this.doubleTapFirstTap) {\n const tapX =\n this.props.staticPinPosition.x - this.doubleTapFirstTap.x;\n const tapY =\n this.props.staticPinPosition.y - this.doubleTapFirstTap.y;\n\n Animated.timing(this.panAnim, {\n toValue: {\n x: this.offsetX + tapX / this.zoomLevel,\n y: this.offsetY + tapY / this.zoomLevel,\n },\n useNativeDriver: true,\n duration: 200,\n }).start(() => {\n this._updateStaticPin();\n });\n }\n\n this.props.onSingleTap?.(e, this._getZoomableViewEventObject());\n }, this.props.doubleTapDelay);\n }\n };\n\n moveStaticPinTo = (position: Vec2D) => {\n const { originalWidth, originalHeight } = this.state;\n const { staticPinPosition, contentWidth, contentHeight } = this.props;\n\n if (!staticPinPosition) return;\n if (!originalWidth || !originalHeight) return;\n if (!contentWidth || !contentHeight) return;\n\n // Offset for the static pin\n const pinX = staticPinPosition.x - originalWidth / 2;\n const pinY = staticPinPosition.y - originalHeight / 2;\n\n this.offsetX = contentWidth / 2 - position.x + pinX / this.zoomLevel;\n this.offsetY = contentHeight / 2 - position.y + pinY / this.zoomLevel;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n };\n\n private _staticPinPosition = () => {\n if (!this.props.staticPinPosition) return;\n if (!this.props.contentWidth || !this.props.contentHeight) return;\n\n return viewportPositionToImagePosition({\n viewportPosition: {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n },\n imageSize: {\n height: this.props.contentHeight,\n width: this.props.contentWidth,\n },\n zoomableEvent: {\n ...this._getZoomableViewEventObject(),\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n zoomLevel: this.zoomLevel,\n },\n });\n };\n\n private _updateStaticPin = () => {\n const position = this._staticPinPosition();\n if (!position) return;\n this.props.onStaticPinPositionChange?.(position);\n };\n\n private _addTouch(touch: TouchPoint) {\n this.touches.push(touch);\n this.setState({ touches: [...this.touches] });\n }\n\n private _removeTouch(touch: TouchPoint) {\n this.touches.splice(this.touches.indexOf(touch), 1);\n this.setState({ touches: [...this.touches] });\n }\n\n /**\n * Handles the double tap event\n *\n * @param e\n *\n * @private\n */\n _handleDoubleTap(e: GestureResponderEvent) {\n const { onDoubleTapBefore, onDoubleTapAfter, doubleTapZoomToCenter } =\n this.props;\n\n onDoubleTapBefore?.(e, this._getZoomableViewEventObject());\n\n const nextZoomStep = this._getNextZoomStep();\n if (nextZoomStep == null) return;\n\n const { originalPageX, originalPageY } = this.state;\n if (originalPageX == null) return;\n if (originalPageY == null) return;\n\n // define new zoom position coordinates\n const zoomPositionCoordinates = {\n x: e.nativeEvent.pageX - originalPageX,\n y: e.nativeEvent.pageY - originalPageY,\n };\n\n // if doubleTapZoomToCenter enabled -> always zoom to center instead\n if (doubleTapZoomToCenter) {\n zoomPositionCoordinates.x = 0;\n zoomPositionCoordinates.y = 0;\n }\n\n this._zoomToLocation(\n zoomPositionCoordinates.x,\n zoomPositionCoordinates.y,\n nextZoomStep\n );\n\n onDoubleTapAfter?.(\n e,\n this._getZoomableViewEventObject({ zoomLevel: nextZoomStep })\n );\n }\n\n /**\n * Returns the next zoom step based on current step and zoomStep property.\n * If we are zoomed all the way in -> return to initialzoom\n *\n * @returns {*}\n */\n _getNextZoomStep() {\n const { zoomStep, maxZoom, initialZoom } = this.props;\n const { zoomLevel } = this;\n\n if (maxZoom == null) return;\n\n if (zoomLevel.toFixed(2) === maxZoom.toFixed(2)) {\n return initialZoom;\n }\n\n if (zoomStep == null) return;\n\n const nextZoomStep = zoomLevel * (1 + zoomStep);\n if (nextZoomStep > maxZoom) {\n return maxZoom;\n }\n\n return nextZoomStep;\n }\n\n /**\n * Zooms to a specific location in our view\n *\n * @param x\n * @param y\n * @param newZoomLevel\n *\n * @private\n */\n _zoomToLocation(x: number, y: number, newZoomLevel: number) {\n if (!this.props.zoomEnabled) return;\n if (this.state.originalWidth == null) return;\n if (this.state.originalHeight == null) return;\n\n this.props.onZoomBefore?.(null, null, this._getZoomableViewEventObject());\n\n // == Perform Zoom Animation ==\n // Calculates panAnim values based on changes in zoomAnim.\n let prevScale = this.zoomLevel;\n // Since zoomAnim is calculated in native driver,\n // it will jitter panAnim once in a while,\n // because here panAnim is being calculated in js.\n // However the jittering should mostly occur in simulator.\n const listenerId = this.zoomAnim.addListener(({ value: newScale }) => {\n if (this.state.originalWidth == null) return;\n if (this.state.originalHeight == null) return;\n this.panAnim.setValue({\n x: calcNewScaledOffsetForZoomCentering(\n this.offsetX,\n this.state.originalWidth,\n prevScale,\n newScale,\n x\n ),\n y: calcNewScaledOffsetForZoomCentering(\n this.offsetY,\n this.state.originalHeight,\n prevScale,\n newScale,\n y\n ),\n });\n prevScale = newScale;\n });\n getZoomToAnimation(this.zoomAnim, newZoomLevel).start(() => {\n this.zoomAnim.removeListener(listenerId);\n });\n // == Zoom Animation Ends ==\n\n this.props.onZoomAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Zooms to a specificied zoom level.\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number} newZoomLevel\n *\n * @return {bool}\n */\n zoomTo(newZoomLevel: number) {\n if (\n // if we would go out of our min/max limits -> abort\n (this.props.maxZoom && newZoomLevel > this.props.maxZoom) ||\n (this.props.minZoom && newZoomLevel < this.props.minZoom)\n )\n return false;\n\n this._zoomToLocation(0, 0, newZoomLevel);\n return true;\n }\n\n /**\n * Zooms in or out by a specified change level\n * Use a positive number for `zoomLevelChange` to zoom in\n * Use a negative number for `zoomLevelChange` to zoom out\n *\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number | null} zoomLevelChange\n *\n * @return {bool}\n */\n zoomBy(zoomLevelChange: number) {\n // if no zoom level Change given -> just use zoom step\n zoomLevelChange ||= this.props.zoomStep || 0;\n return this.zoomTo(this.zoomLevel + zoomLevelChange);\n }\n\n /**\n * Moves the zoomed view to a specified position\n * Returns a promise when finished\n *\n * @param {number} newOffsetX the new position we want to move it to (x-axis)\n * @param {number} newOffsetY the new position we want to move it to (y-axis)\n *\n * @return {bool}\n */\n moveTo(newOffsetX: number, newOffsetY: number) {\n const { originalWidth, originalHeight } = this.state;\n if (!originalWidth || !originalHeight) return;\n\n const offsetX = (newOffsetX - originalWidth / 2) / this.zoomLevel;\n const offsetY = (newOffsetY - originalHeight / 2) / this.zoomLevel;\n\n this._setNewOffsetPosition(-offsetX, -offsetY);\n }\n\n /**\n * Moves the zoomed view by a certain amount.\n *\n * Returns a promise when finished\n *\n * @param {number} offsetChangeX the amount we want to move the offset by (x-axis)\n * @param {number} offsetChangeY the amount we want to move the offset by (y-axis)\n *\n * @return {bool}\n */\n moveBy(offsetChangeX: number, offsetChangeY: number) {\n const offsetX =\n (this.offsetX * this.zoomLevel - offsetChangeX) / this.zoomLevel;\n const offsetY =\n (this.offsetY * this.zoomLevel - offsetChangeY) / this.zoomLevel;\n\n this._setNewOffsetPosition(offsetX, offsetY);\n }\n\n render() {\n const {\n staticPinIcon,\n children,\n visualTouchFeedbackEnabled,\n doubleTapDelay,\n staticPinPosition,\n onStaticPinLongPress,\n onStaticPinPress,\n pinProps,\n } = this.props;\n const { pinSize, touches, debugPoints = [] } = this.state;\n\n return (\n \n \n {children}\n \n\n {visualTouchFeedbackEnabled &&\n touches?.map(\n (touch) =>\n doubleTapDelay && (\n {\n this._removeTouch(touch);\n }}\n />\n )\n )}\n\n {/* For Debugging Only */}\n {debugPoints.map(({ x, y }, index) => {\n return ;\n })}\n\n {staticPinPosition && (\n {\n this.setState({ pinSize: size });\n }}\n pinProps={pinProps}\n />\n )}\n \n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n overflow: 'hidden',\n position: 'relative',\n },\n zoomSubject: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n width: '100%',\n },\n});\n\nexport default ReactNativeZoomableView;\n\nexport { ReactNativeZoomableView };\n"]} \ No newline at end of file +{"version":3,"sources":["ReactNativeZoomableView.tsx"],"names":["React","Component","createRef","Animated","Easing","PanResponder","StyleSheet","View","AnimatedTouchFeedback","DebugTouchPoint","calcGestureCenterPoint","calcGestureTouchDistance","calcNewScaledOffsetForZoomCentering","applyPanBoundariesToOffset","viewportPositionToImagePosition","StaticPin","debounce","getBoundaryCrossedAnim","getPanMomentumDecayAnim","getZoomToAnimation","initialState","originalWidth","originalHeight","originalPageX","originalPageY","pinSize","width","height","ReactNativeZoomableView","gestureStarted","v","_gestureStarted","constructor","props","ValueXY","x","y","Value","value","boundaryCrossedAnimInEffect","position","onStaticPinPositionChange","requestAnimationFrame","setTimeout","zoomSubjectWrapperRef","current","measureInWindow","setState","e","gestureState","onStartShouldSetPanResponder","_getZoomableViewEventObject","onLongPress","longPressTimeout","longPressDuration","onPanResponderGrant","panAnim","stopAnimation","zoomAnim","raisePin","gestureType","_resolveAndHandleTap","debugPoints","lastGestureCenterPosition","disableMomentum","panEnabled","disablePanOnInitialZoom","zoomLevel","initialZoom","vx","vy","start","clearTimeout","onPanResponderEnd","onZoomEnd","onShiftingEnd","staticPinPosition","_updateStaticPin","dropPin","onPanResponderMove","numberActiveTouches","_handlePanResponderGrant","_handlePanResponderEnd","lastGestureTouchDistance","_handlePinching","Math","abs","dx","dy","isShiftGesture","_handleShifting","now","Date","doubleTapFirstTapReleaseTimestamp","doubleTapDelay","doubleTapFirstTap","_addTouch","id","toString","isSecondTap","singleTapTimeoutId","_handleDoubleTap","nativeEvent","pageX","state","pageY","persist","tapX","tapY","timing","toValue","offsetX","offsetY","useNativeDriver","duration","onSingleTap","contentWidth","contentHeight","pinX","pinY","setValue","viewportPosition","imageSize","zoomableEvent","_staticPinPosition","gestureHandlers","create","_handleStartShouldSetPanResponder","_handlePanResponderMove","onPanResponderRelease","onPanResponderTerminate","evt","onPanResponderTerminationRequest","onShouldBlockNativeResponder","onStartShouldSetPanResponderCapture","onMoveShouldSetPanResponderCapture","zoomAnimatedValue","panAnimatedValueXY","initialOffsetX","initialOffsetY","addListener","animatePin","pinAnim","easing","out","ease","__setOffset","__getOffset","axis","offset","offsetState","__offsets","bindToBorders","containerSize","contentSize","boundOffset","panBoundaryPadding","boundariesApplied","toFixed","componentDidUpdate","prevProps","prevState","zoomEnabled","onTransformInvocationInitialized","_invokeOnTransform","successful","currState","originalMeasurementsChanged","staticPinPositionChanged","componentDidMount","grabZoomSubjectOriginalMeasurements","measureZoomSubjectInterval","setInterval","componentWillUnmount","clearInterval","zoomableViewEvent","onTransform","onStaticPinPositionMove","debouncedOnStaticPinPositionChange","overwriteObj","maxZoom","minZoom","pinchToZoomInSensitivity","pinchToZoomOutSensitivity","distance","onZoomBefore","zoomGrowthFromLastGestureState","pinchToZoomSensitivity","deltaGrowth","deltaGrowthAdjustedBySensitivity","newZoomLevel","gestureCenterPoint","zoomCenter","debug","_setPinchDebugPoints","oldOffsetX","oldOffsetY","oldScale","newScale","offsetShift","_calcOffsetShiftSinceLastGestureState","onZoomAfter","gestureResponderEvent","points","touches","movementSensibility","shift","shiftX","shiftY","moveX","moveY","_setNewOffsetPosition","newOffsetX","newOffsetY","onShiftingBefore","onShiftingAfter","touch","push","_removeTouch","splice","indexOf","onDoubleTapBefore","onDoubleTapAfter","doubleTapZoomToCenter","nextZoomStep","_getNextZoomStep","zoomPositionCoordinates","_zoomToLocation","zoomStep","prevScale","listenerId","removeListener","zoomTo","zoomBy","zoomLevelChange","moveTo","moveBy","offsetChangeX","offsetChangeY","render","staticPinIcon","children","visualTouchFeedbackEnabled","onStaticPinLongPress","onStaticPinPress","pinProps","styles","container","panHandlers","zoomSubject","style","transform","scale","getTranslateTransform","map","index","size","undefined","alignItems","flex","justifyContent","overflow"],"mappings":"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","sourcesContent":["import React, { Component, createRef, RefObject } from 'react';\nimport {\n Animated,\n Easing,\n GestureResponderEvent,\n PanResponder,\n PanResponderCallbacks,\n PanResponderGestureState,\n PanResponderInstance,\n StyleSheet,\n View,\n} from 'react-native';\n\nimport {\n Vec2D,\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState,\n TouchPoint,\n ZoomableViewEvent,\n Size2D,\n} from './typings';\n\nimport { AnimatedTouchFeedback } from './components';\nimport { DebugTouchPoint } from './debugHelper';\nimport {\n calcGestureCenterPoint,\n calcGestureTouchDistance,\n calcNewScaledOffsetForZoomCentering,\n} from './helper';\nimport { applyPanBoundariesToOffset } from './helper/applyPanBoundariesToOffset';\nimport { viewportPositionToImagePosition } from './helper/coordinateConversion';\nimport { StaticPin } from './components/StaticPin';\nimport { debounce } from 'lodash';\nimport {\n getBoundaryCrossedAnim,\n getPanMomentumDecayAnim,\n getZoomToAnimation,\n} from './animations';\n\nconst initialState: ReactNativeZoomableViewState = {\n originalWidth: 0,\n originalHeight: 0,\n originalPageX: 0,\n originalPageY: 0,\n pinSize: { width: 0, height: 0 },\n};\n\nclass ReactNativeZoomableView extends Component<\n ReactNativeZoomableViewProps,\n ReactNativeZoomableViewState\n> {\n zoomSubjectWrapperRef: RefObject;\n gestureHandlers: PanResponderInstance;\n doubleTapFirstTapReleaseTimestamp: number | undefined;\n\n static defaultProps = {\n zoomEnabled: true,\n panEnabled: true,\n initialZoom: 1,\n initialOffsetX: 0,\n initialOffsetY: 0,\n maxZoom: 1.5,\n minZoom: 0.5,\n pinchToZoomInSensitivity: 1,\n pinchToZoomOutSensitivity: 1,\n movementSensibility: 1,\n doubleTapDelay: 300,\n bindToBorders: true,\n zoomStep: 0.5,\n onLongPress: null,\n longPressDuration: 700,\n contentWidth: undefined,\n contentHeight: undefined,\n panBoundaryPadding: 0,\n visualTouchFeedbackEnabled: true,\n staticPinPosition: undefined,\n staticPinIcon: undefined,\n onStaticPinPositionChange: undefined,\n onStaticPinPositionMove: undefined,\n animatePin: true,\n disablePanOnInitialZoom: false,\n };\n\n private panAnim = new Animated.ValueXY({ x: 0, y: 0 });\n private zoomAnim = new Animated.Value(1);\n private pinAnim = new Animated.ValueXY({ x: 0, y: 0 });\n\n private __offsets = {\n x: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n y: {\n value: 0,\n boundaryCrossedAnimInEffect: false,\n },\n };\n\n private zoomLevel = 1;\n private lastGestureCenterPosition: { x: number; y: number } | null = null;\n private lastGestureTouchDistance: number | null = null;\n private gestureType: 'pinch' | 'shift' | null;\n\n private _gestureStarted = false;\n private set gestureStarted(v: boolean) {\n this._gestureStarted = v;\n }\n\n public get gestureStarted() {\n return this._gestureStarted;\n }\n\n /**\n * Last press time (used to evaluate whether user double tapped)\n * @type {number}\n */\n private longPressTimeout: NodeJS.Timeout | null = null;\n private onTransformInvocationInitialized: boolean | undefined;\n private singleTapTimeoutId: NodeJS.Timeout | undefined;\n private touches: TouchPoint[] = [];\n private doubleTapFirstTap: TouchPoint | undefined;\n private measureZoomSubjectInterval: NodeJS.Timer | undefined;\n\n constructor(props: ReactNativeZoomableViewProps) {\n super(props);\n // This needs to be done before anything else to initialize the state.\n // Otherwise, the logic below may reference the state when it's undefined,\n // causing runtime errors.\n this.state = { ...initialState };\n\n this.gestureHandlers = PanResponder.create({\n onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,\n onPanResponderGrant: this._handlePanResponderGrant,\n onPanResponderMove: this._handlePanResponderMove,\n onPanResponderRelease: this._handlePanResponderEnd,\n onPanResponderTerminate: (evt, gestureState) => {\n // We should also call _handlePanResponderEnd\n // to properly perform cleanups when the gesture is terminated\n // (aka gesture handling responsibility is taken over by another component).\n // This also fixes a weird issue where\n // on real device, sometimes onPanResponderRelease is not called when you lift 2 fingers up,\n // but onPanResponderTerminate is called instead for no apparent reason.\n this._handlePanResponderEnd(evt, gestureState);\n this.props.onPanResponderTerminate?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n );\n },\n onPanResponderTerminationRequest: (evt, gestureState) =>\n !!this.props.onPanResponderTerminationRequest?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ),\n // Defaults to true to prevent parent components, such as React Navigation's tab view, from taking over as responder.\n onShouldBlockNativeResponder: (evt, gestureState) =>\n this.props.onShouldBlockNativeResponder?.(\n evt,\n gestureState,\n this._getZoomableViewEventObject()\n ) ?? true,\n onStartShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onStartShouldSetPanResponderCapture?.(evt, gestureState),\n onMoveShouldSetPanResponderCapture: (evt, gestureState) =>\n !!this.props.onMoveShouldSetPanResponderCapture?.(evt, gestureState),\n });\n\n this.zoomSubjectWrapperRef = createRef();\n\n if (this.props.zoomAnimatedValue)\n this.zoomAnim = this.props.zoomAnimatedValue;\n if (this.props.panAnimatedValueXY)\n this.panAnim = this.props.panAnimatedValueXY;\n\n if (this.props.initialZoom) this.zoomLevel = this.props.initialZoom;\n if (this.props.initialOffsetX != null)\n this.offsetX = this.props.initialOffsetX;\n if (this.props.initialOffsetY != null)\n this.offsetY = this.props.initialOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n this.panAnim.addListener(({ x, y }) => {\n this.offsetX = x;\n this.offsetY = y;\n });\n this.zoomAnim.addListener(({ value }) => {\n this.zoomLevel = value;\n });\n\n this.lastGestureTouchDistance = 150;\n\n this.gestureType = null;\n }\n\n private raisePin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: -10 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private dropPin() {\n if (!this.props.animatePin) return;\n Animated.timing(this.pinAnim, {\n toValue: { x: 0, y: 0 },\n useNativeDriver: true,\n easing: Easing.out(Easing.ease),\n duration: 100,\n }).start();\n }\n\n private set offsetX(x: number) {\n this.__setOffset('x', x);\n }\n\n private set offsetY(y: number) {\n this.__setOffset('y', y);\n }\n\n private get offsetX() {\n return this.__getOffset('x');\n }\n\n private get offsetY() {\n return this.__getOffset('y');\n }\n\n private __setOffset(axis: 'x' | 'y', offset: number) {\n const offsetState = this.__offsets[axis];\n\n if (this.props.bindToBorders) {\n const containerSize =\n axis === 'x' ? this.state.originalWidth : this.state.originalHeight;\n const contentSize =\n axis === 'x'\n ? this.props.contentWidth || this.state.originalWidth\n : this.props.contentHeight || this.state.originalHeight;\n\n const boundOffset =\n contentSize && containerSize && this.props.panBoundaryPadding != null\n ? applyPanBoundariesToOffset(\n offset,\n containerSize,\n contentSize,\n this.zoomLevel,\n this.props.panBoundaryPadding\n )\n : offset;\n\n if (!this.gestureType && !offsetState.boundaryCrossedAnimInEffect) {\n const boundariesApplied =\n boundOffset !== offset &&\n boundOffset.toFixed(3) !== offset.toFixed(3);\n if (boundariesApplied) {\n offsetState.boundaryCrossedAnimInEffect = true;\n getBoundaryCrossedAnim(this.panAnim[axis], boundOffset).start(() => {\n offsetState.boundaryCrossedAnimInEffect = false;\n });\n return;\n }\n }\n }\n\n offsetState.value = offset;\n }\n\n private __getOffset(axis: 'x' | 'y') {\n return this.__offsets[axis].value;\n }\n\n componentDidUpdate(\n prevProps: ReactNativeZoomableViewProps,\n prevState: ReactNativeZoomableViewState\n ) {\n const { zoomEnabled, initialZoom } = this.props;\n if (prevProps.zoomEnabled && !zoomEnabled && initialZoom) {\n this.zoomLevel = initialZoom;\n this.zoomAnim.setValue(this.zoomLevel);\n }\n if (\n !this.onTransformInvocationInitialized &&\n this._invokeOnTransform().successful\n ) {\n this.panAnim.addListener(() => this._invokeOnTransform());\n this.zoomAnim.addListener(() => this._invokeOnTransform());\n this.onTransformInvocationInitialized = true;\n }\n\n const currState = this.state;\n const originalMeasurementsChanged =\n currState.originalHeight !== prevState.originalHeight ||\n currState.originalWidth !== prevState.originalWidth ||\n currState.originalPageX !== prevState.originalPageX ||\n currState.originalPageY !== prevState.originalPageY;\n\n const staticPinPositionChanged =\n prevProps.staticPinPosition?.x !== this.props.staticPinPosition?.x ||\n prevProps.staticPinPosition?.y !== this.props.staticPinPosition?.y;\n\n if (\n this.onTransformInvocationInitialized &&\n (originalMeasurementsChanged || staticPinPositionChanged)\n ) {\n this._invokeOnTransform();\n }\n }\n\n componentDidMount() {\n this.grabZoomSubjectOriginalMeasurements();\n // We've already run `grabZoomSubjectOriginalMeasurements` at various events\n // to make sure the measurements are promptly updated.\n // However, there might be cases we haven't accounted for, especially when\n // native processes are involved. To account for those cases,\n // we'll use an interval here to ensure we're always up-to-date.\n // The `setState` in `grabZoomSubjectOriginalMeasurements` won't trigger a rerender\n // if the values given haven't changed, so we're not running performance risk here.\n this.measureZoomSubjectInterval = setInterval(\n this.grabZoomSubjectOriginalMeasurements,\n 1e3\n );\n }\n\n componentWillUnmount() {\n this.measureZoomSubjectInterval &&\n clearInterval(this.measureZoomSubjectInterval);\n }\n\n debouncedOnStaticPinPositionChange = debounce(\n (position: Vec2D) => this.props.onStaticPinPositionChange?.(position),\n 100\n );\n\n /**\n * try to invoke onTransform\n * @private\n */\n _invokeOnTransform() {\n const zoomableViewEvent = this._getZoomableViewEventObject();\n const position = this._staticPinPosition();\n\n if (!zoomableViewEvent.originalWidth || !zoomableViewEvent.originalHeight)\n return { successful: false };\n\n this.props.onTransform?.(zoomableViewEvent);\n\n if (position) {\n this.props.onStaticPinPositionMove?.(position);\n this.debouncedOnStaticPinPositionChange(position);\n }\n\n return { successful: true };\n }\n\n /**\n * Returns additional information about components current state for external event hooks\n *\n * @returns {{}}\n * @private\n */\n _getZoomableViewEventObject(overwriteObj = {}): ZoomableViewEvent {\n return {\n zoomLevel: this.zoomLevel,\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n originalHeight: this.state.originalHeight,\n originalWidth: this.state.originalWidth,\n originalPageX: this.state.originalPageX,\n originalPageY: this.state.originalPageY,\n ...overwriteObj,\n } as ZoomableViewEvent;\n }\n\n /**\n * Get the original box dimensions and save them for later use.\n * (They will be used to calculate boxBorders)\n *\n * @private\n */\n private grabZoomSubjectOriginalMeasurements = () => {\n // make sure we measure after animations are complete\n requestAnimationFrame(() => {\n // this setTimeout is here to fix a weird issue on iOS where the measurements are all `0`\n // when navigating back (react-navigation stack) from another view\n // while closing the keyboard at the same time\n setTimeout(() => {\n // In normal conditions, we're supposed to measure zoomSubject instead of its wrapper.\n // However, our zoomSubject may have been transformed by an initial zoomLevel or offset,\n // in which case these measurements will not represent the true \"original\" measurements.\n // We just need to make sure the zoomSubjectWrapper perfectly aligns with the zoomSubject\n // (no border, space, or anything between them)\n const zoomSubjectWrapperRef = this.zoomSubjectWrapperRef;\n // we don't wanna measure when zoomSubjectWrapperRef is not yet available or has been unmounted\n zoomSubjectWrapperRef.current?.measureInWindow(\n (x, y, width, height) => {\n // When the component is off-screen, these become all 0s, so we don't set them\n // to avoid messing up calculations, especially ones that are done right after\n // the component transitions from hidden to visible.\n if (!x && !y && !width && !height) return;\n this.setState({\n originalWidth: width,\n originalHeight: height,\n originalPageX: x,\n originalPageY: y,\n });\n }\n );\n });\n });\n };\n\n /**\n * Handles the start of touch events and checks for taps\n *\n * @param e\n * @param gestureState\n * @returns {boolean}\n *\n * @private\n */\n _handleStartShouldSetPanResponder = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onStartShouldSetPanResponder) {\n this.props.onStartShouldSetPanResponder(\n e,\n gestureState,\n this._getZoomableViewEventObject(),\n false\n );\n }\n\n // Always set pan responder on start\n // of gesture so we can handle tap.\n // \"Pan threshold validation\" will be handled\n // in `onPanResponderMove` instead of in `onMoveShouldSetPanResponder`\n return true;\n };\n\n /**\n * Calculates pinch distance\n *\n * @param e\n * @param gestureState\n * @private\n */\n _handlePanResponderGrant: NonNullable<\n PanResponderCallbacks['onPanResponderGrant']\n > = (e, gestureState) => {\n if (this.props.onLongPress) {\n this.longPressTimeout = setTimeout(() => {\n this.props.onLongPress?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n this.longPressTimeout = null;\n }, this.props.longPressDuration);\n }\n\n this.props.onPanResponderGrant?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n this.panAnim.stopAnimation();\n this.zoomAnim.stopAnimation();\n this.gestureStarted = true;\n\n this.raisePin();\n };\n\n /**\n * Handles the end of touch events\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderEnd: NonNullable<\n PanResponderCallbacks['onPanResponderEnd']\n > = (e, gestureState) => {\n if (!this.gestureType) {\n this._resolveAndHandleTap(e);\n }\n\n this.setState({ debugPoints: [] });\n\n this.lastGestureCenterPosition = null;\n\n const disableMomentum =\n this.props.disableMomentum ||\n (this.props.panEnabled &&\n this.gestureType === 'shift' &&\n this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom);\n\n // Trigger final shift animation unless disablePanOnInitialZoom is set and we're on the initial zoom level\n // or disableMomentum\n if (!disableMomentum) {\n getPanMomentumDecayAnim(this.panAnim, {\n x: gestureState.vx / this.zoomLevel,\n y: gestureState.vy / this.zoomLevel,\n }).start();\n }\n\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n this.props.onPanResponderEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n\n if (this.gestureType === 'pinch') {\n this.props.onZoomEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n } else if (this.gestureType === 'shift') {\n this.props.onShiftingEnd?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n if (this.props.staticPinPosition) {\n this._updateStaticPin();\n }\n\n this.dropPin();\n\n this.gestureType = null;\n this.gestureStarted = false;\n };\n\n /**\n * Handles the actual movement of our pan responder\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePanResponderMove = (\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => {\n if (this.props.onPanResponderMove) {\n if (\n this.props.onPanResponderMove(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return false;\n }\n }\n\n // Only supports 2 touches and below,\n // any invalid number will cause the gesture to end.\n if (gestureState.numberActiveTouches <= 2) {\n if (!this.gestureStarted) {\n this._handlePanResponderGrant(e, gestureState);\n }\n } else {\n if (this.gestureStarted) {\n this._handlePanResponderEnd(e, gestureState);\n }\n return true;\n }\n\n if (gestureState.numberActiveTouches === 2) {\n if (this.longPressTimeout) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'pinch') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n this.lastGestureTouchDistance = calcGestureTouchDistance(\n e,\n gestureState\n );\n }\n this.gestureType = 'pinch';\n this._handlePinching(e, gestureState);\n } else if (gestureState.numberActiveTouches === 1) {\n if (\n this.longPressTimeout &&\n (Math.abs(gestureState.dx) > 5 || Math.abs(gestureState.dy) > 5)\n ) {\n clearTimeout(this.longPressTimeout);\n this.longPressTimeout = null;\n }\n // change some measurement states when switching gesture to ensure a smooth transition\n if (this.gestureType !== 'shift') {\n this.lastGestureCenterPosition = calcGestureCenterPoint(\n e,\n gestureState\n );\n }\n\n const { dx, dy } = gestureState;\n const isShiftGesture = Math.abs(dx) > 2 || Math.abs(dy) > 2;\n if (isShiftGesture) {\n this.gestureType = 'shift';\n this._handleShifting(gestureState);\n }\n }\n };\n\n /**\n * Handles the pinch movement and zooming\n *\n * @param e\n * @param gestureState\n *\n * @private\n */\n _handlePinching(\n e: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) {\n if (!this.props.zoomEnabled) return;\n\n const {\n maxZoom,\n minZoom,\n pinchToZoomInSensitivity,\n pinchToZoomOutSensitivity,\n } = this.props;\n\n const distance = calcGestureTouchDistance(e, gestureState);\n\n if (\n this.props.onZoomBefore &&\n this.props.onZoomBefore(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n )\n ) {\n return;\n }\n\n if (!distance) return;\n if (!this.lastGestureTouchDistance) return;\n\n // define the new zoom level and take zoom level sensitivity into consideration\n const zoomGrowthFromLastGestureState =\n distance / this.lastGestureTouchDistance;\n this.lastGestureTouchDistance = distance;\n\n const pinchToZoomSensitivity =\n zoomGrowthFromLastGestureState < 1\n ? pinchToZoomOutSensitivity\n : pinchToZoomInSensitivity;\n\n if (pinchToZoomSensitivity == null) return;\n const deltaGrowth = zoomGrowthFromLastGestureState - 1;\n // 0 - no resistance\n // 10 - 90% resistance\n const deltaGrowthAdjustedBySensitivity =\n deltaGrowth * (1 - (pinchToZoomSensitivity * 9) / 100);\n\n let newZoomLevel = this.zoomLevel * (1 + deltaGrowthAdjustedBySensitivity);\n\n // make sure max and min zoom levels are respected\n if (maxZoom != null && newZoomLevel > maxZoom) {\n newZoomLevel = maxZoom;\n }\n\n if (minZoom != null && newZoomLevel < minZoom) {\n newZoomLevel = minZoom;\n }\n\n const gestureCenterPoint = calcGestureCenterPoint(e, gestureState);\n\n if (!gestureCenterPoint) return;\n\n let zoomCenter = {\n x: gestureCenterPoint.x - this.state.originalPageX,\n y: gestureCenterPoint.y - this.state.originalPageY,\n };\n\n if (this.props.staticPinPosition) {\n // When we use a static pin position, the zoom centre is the same as that position,\n // otherwise the pin moves around way too much while zooming.\n zoomCenter = {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n };\n }\n\n // Uncomment to debug\n this.props.debug && this._setPinchDebugPoints(e, zoomCenter);\n\n const { originalHeight, originalWidth } = this.state;\n\n const oldOffsetX = this.offsetX;\n const oldOffsetY = this.offsetY;\n const oldScale = this.zoomLevel;\n const newScale = newZoomLevel;\n\n if (!originalHeight || !originalWidth) return;\n\n let offsetY = calcNewScaledOffsetForZoomCentering(\n oldOffsetY,\n originalHeight,\n oldScale,\n newScale,\n zoomCenter.y\n );\n let offsetX = calcNewScaledOffsetForZoomCentering(\n oldOffsetX,\n originalWidth,\n oldScale,\n newScale,\n zoomCenter.x\n );\n\n const offsetShift =\n this._calcOffsetShiftSinceLastGestureState(gestureCenterPoint);\n if (offsetShift) {\n offsetX += offsetShift.x;\n offsetY += offsetShift.y;\n }\n\n this.offsetX = offsetX;\n this.offsetY = offsetY;\n this.zoomLevel = newScale;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n this.props.onZoomAfter?.(\n e,\n gestureState,\n this._getZoomableViewEventObject()\n );\n }\n\n /**\n * Used to debug pinch events\n * @param gestureResponderEvent\n * @param zoomCenter\n * @param points\n */\n _setPinchDebugPoints(\n gestureResponderEvent: GestureResponderEvent,\n zoomCenter: Vec2D,\n ...points: Vec2D[]\n ) {\n const { touches } = gestureResponderEvent.nativeEvent;\n const { originalPageY, originalPageX } = this.state;\n\n this.setState({\n debugPoints: [\n {\n x: touches[0].pageX - originalPageX,\n y: touches[0].pageY - originalPageY,\n },\n {\n x: touches[1].pageX - originalPageX,\n y: touches[1].pageY - originalPageY,\n },\n zoomCenter,\n ...points,\n ],\n });\n }\n\n /**\n * Calculates the amount the offset should shift since the last position during panning\n *\n * @param {Vec2D} gestureCenterPoint\n *\n * @private\n */\n _calcOffsetShiftSinceLastGestureState(gestureCenterPoint: Vec2D) {\n const { movementSensibility } = this.props;\n\n let shift = null;\n\n if (this.lastGestureCenterPosition && movementSensibility) {\n const dx = gestureCenterPoint.x - this.lastGestureCenterPosition.x;\n const dy = gestureCenterPoint.y - this.lastGestureCenterPosition.y;\n\n const shiftX = dx / this.zoomLevel / movementSensibility;\n const shiftY = dy / this.zoomLevel / movementSensibility;\n\n shift = {\n x: shiftX,\n y: shiftY,\n };\n }\n\n this.lastGestureCenterPosition = gestureCenterPoint;\n\n return shift;\n }\n\n /**\n * Handles movement by tap and move\n *\n * @param gestureState\n *\n * @private\n */\n _handleShifting(gestureState: PanResponderGestureState) {\n // Skips shifting if panEnabled is false or disablePanOnInitialZoom is true and we're on the initial zoom level\n if (\n !this.props.panEnabled ||\n (this.props.disablePanOnInitialZoom &&\n this.zoomLevel === this.props.initialZoom)\n ) {\n return;\n }\n const shift = this._calcOffsetShiftSinceLastGestureState({\n x: gestureState.moveX,\n y: gestureState.moveY,\n });\n if (!shift) return;\n\n const offsetX = this.offsetX + shift.x;\n const offsetY = this.offsetY + shift.y;\n\n if (\n this.props.debug &&\n this.state.originalPageX &&\n this.state.originalPageY\n ) {\n const x = gestureState.moveX - this.state.originalPageX;\n const y = gestureState.moveY - this.state.originalPageY;\n this.setState({ debugPoints: [{ x, y }] });\n }\n\n this._setNewOffsetPosition(offsetX, offsetY);\n\n this.raisePin();\n }\n\n /**\n * Set the state to offset moved\n *\n * @param {number} newOffsetX\n * @param {number} newOffsetY\n * @returns\n */\n _setNewOffsetPosition(newOffsetX: number, newOffsetY: number) {\n const { onShiftingBefore, onShiftingAfter } = this.props;\n\n if (onShiftingBefore?.(null, null, this._getZoomableViewEventObject())) {\n return;\n }\n\n this.offsetX = newOffsetX;\n this.offsetY = newOffsetY;\n\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n this.zoomAnim.setValue(this.zoomLevel);\n\n onShiftingAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Check whether the press event is double tap\n * or single tap and handle the event accordingly\n *\n * @param e\n *\n * @private\n */\n private _resolveAndHandleTap = (e: GestureResponderEvent) => {\n const now = Date.now();\n if (\n this.doubleTapFirstTapReleaseTimestamp &&\n this.props.doubleTapDelay &&\n now - this.doubleTapFirstTapReleaseTimestamp < this.props.doubleTapDelay\n ) {\n this.doubleTapFirstTap &&\n this._addTouch({\n ...this.doubleTapFirstTap,\n id: now.toString(),\n isSecondTap: true,\n });\n this.singleTapTimeoutId && clearTimeout(this.singleTapTimeoutId);\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n delete this.doubleTapFirstTap;\n this._handleDoubleTap(e);\n } else {\n this.doubleTapFirstTapReleaseTimestamp = now;\n this.doubleTapFirstTap = {\n id: now.toString(),\n x: e.nativeEvent.pageX - this.state.originalPageX,\n y: e.nativeEvent.pageY - this.state.originalPageY,\n };\n this._addTouch(this.doubleTapFirstTap);\n\n // persist event so e.nativeEvent is preserved after a timeout delay\n e.persist();\n this.singleTapTimeoutId = setTimeout(() => {\n delete this.doubleTapFirstTapReleaseTimestamp;\n delete this.singleTapTimeoutId;\n\n // Pan to the tapped location\n if (this.props.staticPinPosition && this.doubleTapFirstTap) {\n const tapX =\n this.props.staticPinPosition.x - this.doubleTapFirstTap.x;\n const tapY =\n this.props.staticPinPosition.y - this.doubleTapFirstTap.y;\n\n Animated.timing(this.panAnim, {\n toValue: {\n x: this.offsetX + tapX / this.zoomLevel,\n y: this.offsetY + tapY / this.zoomLevel,\n },\n useNativeDriver: true,\n duration: 200,\n }).start(() => {\n this._updateStaticPin();\n });\n }\n\n this.props.onSingleTap?.(e, this._getZoomableViewEventObject());\n }, this.props.doubleTapDelay);\n }\n };\n\n moveStaticPinTo = (position: Vec2D, duration?: number) => {\n const { originalWidth, originalHeight } = this.state;\n const { staticPinPosition, contentWidth, contentHeight } = this.props;\n\n if (!staticPinPosition) return;\n if (!originalWidth || !originalHeight) return;\n if (!contentWidth || !contentHeight) return;\n\n // Offset for the static pin\n const pinX = staticPinPosition.x - originalWidth / 2;\n const pinY = staticPinPosition.y - originalHeight / 2;\n\n this.offsetX = contentWidth / 2 - position.x + pinX / this.zoomLevel;\n this.offsetY = contentHeight / 2 - position.y + pinY / this.zoomLevel;\n\n if (duration) {\n Animated.timing(this.panAnim, {\n toValue: { x: this.offsetX, y: this.offsetY },\n useNativeDriver: true,\n duration,\n }).start();\n } else {\n this.panAnim.setValue({ x: this.offsetX, y: this.offsetY });\n }\n };\n\n private _staticPinPosition = () => {\n if (!this.props.staticPinPosition) return;\n if (!this.props.contentWidth || !this.props.contentHeight) return;\n\n return viewportPositionToImagePosition({\n viewportPosition: {\n x: this.props.staticPinPosition.x,\n y: this.props.staticPinPosition.y,\n },\n imageSize: {\n height: this.props.contentHeight,\n width: this.props.contentWidth,\n },\n zoomableEvent: {\n ...this._getZoomableViewEventObject(),\n offsetX: this.offsetX,\n offsetY: this.offsetY,\n zoomLevel: this.zoomLevel,\n },\n });\n };\n\n private _updateStaticPin = () => {\n const position = this._staticPinPosition();\n if (!position) return;\n this.props.onStaticPinPositionChange?.(position);\n };\n\n private _addTouch(touch: TouchPoint) {\n this.touches.push(touch);\n this.setState({ touches: [...this.touches] });\n }\n\n private _removeTouch(touch: TouchPoint) {\n this.touches.splice(this.touches.indexOf(touch), 1);\n this.setState({ touches: [...this.touches] });\n }\n\n /**\n * Handles the double tap event\n *\n * @param e\n *\n * @private\n */\n _handleDoubleTap(e: GestureResponderEvent) {\n const { onDoubleTapBefore, onDoubleTapAfter, doubleTapZoomToCenter } =\n this.props;\n\n onDoubleTapBefore?.(e, this._getZoomableViewEventObject());\n\n const nextZoomStep = this._getNextZoomStep();\n if (nextZoomStep == null) return;\n\n const { originalPageX, originalPageY } = this.state;\n\n // define new zoom position coordinates\n const zoomPositionCoordinates = {\n x: e.nativeEvent.pageX - originalPageX,\n y: e.nativeEvent.pageY - originalPageY,\n };\n\n // if doubleTapZoomToCenter enabled -> always zoom to center instead\n if (doubleTapZoomToCenter) {\n zoomPositionCoordinates.x = 0;\n zoomPositionCoordinates.y = 0;\n }\n\n this._zoomToLocation(\n zoomPositionCoordinates.x,\n zoomPositionCoordinates.y,\n nextZoomStep\n );\n\n onDoubleTapAfter?.(\n e,\n this._getZoomableViewEventObject({ zoomLevel: nextZoomStep })\n );\n }\n\n /**\n * Returns the next zoom step based on current step and zoomStep property.\n * If we are zoomed all the way in -> return to initialzoom\n *\n * @returns {*}\n */\n _getNextZoomStep() {\n const { zoomStep, maxZoom, initialZoom } = this.props;\n const { zoomLevel } = this;\n\n if (maxZoom == null) return;\n\n if (zoomLevel.toFixed(2) === maxZoom.toFixed(2)) {\n return initialZoom;\n }\n\n if (zoomStep == null) return;\n\n const nextZoomStep = zoomLevel * (1 + zoomStep);\n if (nextZoomStep > maxZoom) {\n return maxZoom;\n }\n\n return nextZoomStep;\n }\n\n /**\n * Zooms to a specific location in our view\n *\n * @param x\n * @param y\n * @param newZoomLevel\n *\n * @private\n */\n _zoomToLocation(x: number, y: number, newZoomLevel: number) {\n if (!this.props.zoomEnabled) return;\n\n this.props.onZoomBefore?.(null, null, this._getZoomableViewEventObject());\n\n // == Perform Zoom Animation ==\n // Calculates panAnim values based on changes in zoomAnim.\n let prevScale = this.zoomLevel;\n // Since zoomAnim is calculated in native driver,\n // it will jitter panAnim once in a while,\n // because here panAnim is being calculated in js.\n // However the jittering should mostly occur in simulator.\n const listenerId = this.zoomAnim.addListener(({ value: newScale }) => {\n this.panAnim.setValue({\n x: calcNewScaledOffsetForZoomCentering(\n this.offsetX,\n this.state.originalWidth,\n prevScale,\n newScale,\n x\n ),\n y: calcNewScaledOffsetForZoomCentering(\n this.offsetY,\n this.state.originalHeight,\n prevScale,\n newScale,\n y\n ),\n });\n prevScale = newScale;\n });\n getZoomToAnimation(this.zoomAnim, newZoomLevel).start(() => {\n this.zoomAnim.removeListener(listenerId);\n });\n // == Zoom Animation Ends ==\n\n this.props.onZoomAfter?.(null, null, this._getZoomableViewEventObject());\n }\n\n /**\n * Zooms to a specificied zoom level.\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number} newZoomLevel\n *\n * @return {bool}\n */\n zoomTo(newZoomLevel: number) {\n if (\n // if we would go out of our min/max limits -> abort\n (this.props.maxZoom && newZoomLevel > this.props.maxZoom) ||\n (this.props.minZoom && newZoomLevel < this.props.minZoom)\n )\n return false;\n\n this._zoomToLocation(0, 0, newZoomLevel);\n return true;\n }\n\n /**\n * Zooms in or out by a specified change level\n * Use a positive number for `zoomLevelChange` to zoom in\n * Use a negative number for `zoomLevelChange` to zoom out\n *\n * Returns a promise if everything was updated and a boolean, whether it could be updated or if it exceeded the min/max zoom limits.\n *\n * @param {number | null} zoomLevelChange\n *\n * @return {bool}\n */\n zoomBy(zoomLevelChange: number) {\n // if no zoom level Change given -> just use zoom step\n zoomLevelChange ||= this.props.zoomStep || 0;\n return this.zoomTo(this.zoomLevel + zoomLevelChange);\n }\n\n /**\n * Moves the zoomed view to a specified position\n * Returns a promise when finished\n *\n * @param {number} newOffsetX the new position we want to move it to (x-axis)\n * @param {number} newOffsetY the new position we want to move it to (y-axis)\n *\n * @return {bool}\n */\n moveTo(newOffsetX: number, newOffsetY: number) {\n const { originalWidth, originalHeight } = this.state;\n if (!originalWidth || !originalHeight) return;\n\n const offsetX = (newOffsetX - originalWidth / 2) / this.zoomLevel;\n const offsetY = (newOffsetY - originalHeight / 2) / this.zoomLevel;\n\n this._setNewOffsetPosition(-offsetX, -offsetY);\n }\n\n /**\n * Moves the zoomed view by a certain amount.\n *\n * Returns a promise when finished\n *\n * @param {number} offsetChangeX the amount we want to move the offset by (x-axis)\n * @param {number} offsetChangeY the amount we want to move the offset by (y-axis)\n *\n * @return {bool}\n */\n moveBy(offsetChangeX: number, offsetChangeY: number) {\n const offsetX =\n (this.offsetX * this.zoomLevel - offsetChangeX) / this.zoomLevel;\n const offsetY =\n (this.offsetY * this.zoomLevel - offsetChangeY) / this.zoomLevel;\n\n this._setNewOffsetPosition(offsetX, offsetY);\n }\n\n render() {\n const {\n staticPinIcon,\n children,\n visualTouchFeedbackEnabled,\n doubleTapDelay,\n staticPinPosition,\n onStaticPinLongPress,\n onStaticPinPress,\n pinProps,\n } = this.props;\n const { pinSize, touches, debugPoints = [] } = this.state;\n\n return (\n \n \n {children}\n \n\n {visualTouchFeedbackEnabled &&\n touches?.map(\n (touch) =>\n doubleTapDelay && (\n {\n this._removeTouch(touch);\n }}\n />\n )\n )}\n\n {/* For Debugging Only */}\n {debugPoints.map(({ x, y }, index) => {\n return ;\n })}\n\n {staticPinPosition && (\n {\n this.setState({ pinSize: size });\n }}\n pinProps={pinProps}\n />\n )}\n \n );\n }\n}\n\nconst styles = StyleSheet.create({\n container: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n overflow: 'hidden',\n position: 'relative',\n },\n zoomSubject: {\n alignItems: 'center',\n flex: 1,\n justifyContent: 'center',\n width: '100%',\n },\n});\n\nexport default ReactNativeZoomableView;\n\nexport { ReactNativeZoomableView };\n"]} \ No newline at end of file diff --git a/lib/module/typings/index.js.map b/lib/module/typings/index.js.map index 1577fa5..8ced74e 100644 --- a/lib/module/typings/index.js.map +++ b/lib/module/typings/index.js.map @@ -1 +1 @@ -{"version":3,"sources":["index.ts"],"names":["SwipeDirection"],"mappings":"AAOA,WAAYA,cAAZ;;WAAYA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;GAAAA,c,KAAAA,c","sourcesContent":["import {\n Animated,\n GestureResponderEvent,\n PanResponderGestureState,\n ViewProps,\n} from 'react-native';\n\nexport enum SwipeDirection {\n SWIPE_UP = 'SWIPE_UP',\n SWIPE_DOWN = 'SWIPE_DOWN',\n SWIPE_LEFT = 'SWIPE_LEFT',\n SWIPE_RIGHT = 'SWIPE_RIGHT',\n}\n\nexport interface ZoomableViewEvent {\n zoomLevel: number;\n offsetX: number;\n offsetY: number;\n originalHeight: number;\n originalWidth: number;\n originalPageX: number;\n originalPageY: number;\n}\n\nexport interface ReactNativeZoomableViewProps extends ViewProps {\n // options\n zoomEnabled?: boolean;\n panEnabled?: boolean;\n initialZoom?: number;\n initialOffsetX?: number;\n initialOffsetY?: number;\n contentWidth?: number;\n contentHeight?: number;\n panBoundaryPadding?: number;\n maxZoom?: number;\n minZoom?: number;\n doubleTapDelay?: number;\n doubleTapZoomToCenter?: boolean;\n bindToBorders?: boolean;\n zoomStep?: number;\n pinchToZoomInSensitivity?: number;\n pinchToZoomOutSensitivity?: number;\n movementSensibility?: number;\n longPressDuration?: number;\n visualTouchFeedbackEnabled?: boolean;\n disablePanOnInitialZoom?: boolean;\n\n // Zoom animated value ref\n zoomAnimatedValue?: Animated.Value;\n panAnimatedValueXY?: Animated.ValueXY;\n\n // debug\n debug?: boolean;\n\n // callbacks\n onTransform?: (zoomableViewEventObject: ZoomableViewEvent) => void;\n onSingleTap?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapBefore?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapAfter?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onShiftingBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean | undefined;\n onZoomAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onLongPress?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onStartShouldSetPanResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent,\n baseComponentResult: boolean\n ) => boolean;\n onPanResponderGrant?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderMove?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onPanResponderTerminate?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderTerminationRequest?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShouldBlockNativeResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onStartShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onMoveShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onStaticPinPress?: (event: GestureResponderEvent) => void;\n onStaticPinLongPress?: (event: GestureResponderEvent) => void;\n staticPinPosition?: Vec2D;\n staticPinIcon?: React.ReactElement;\n onStaticPinPositionChange?: (position: Vec2D) => void;\n onStaticPinPositionMove?: (position: Vec2D) => void;\n animatePin: boolean;\n pinProps?: ViewProps;\n disableMomentum?: boolean;\n}\n\nexport interface Vec2D {\n x: number;\n y: number;\n}\n\nexport interface Size2D {\n width: number;\n height: number;\n}\n\nexport interface TouchPoint extends Vec2D {\n id: string;\n isSecondTap?: boolean;\n}\n\nexport interface ReactNativeZoomableViewState {\n touches?: TouchPoint[];\n originalWidth: number | null;\n originalHeight: number | null;\n originalPageX: number | null;\n originalPageY: number | null;\n debugPoints?: undefined | Vec2D[];\n pinSize: Size2D;\n}\n\nexport interface ReactNativeZoomableViewWithGesturesProps\n extends ReactNativeZoomableViewProps {\n swipeLengthThreshold?: number;\n swipeVelocityThreshold?: number;\n swipeDirectionalThreshold?: number;\n swipeMinZoom?: number;\n swipeMaxZoom?: number;\n swipeDisabled?: boolean;\n onSwipe?: (\n swipeDirection: SwipeDirection,\n gestureState: PanResponderGestureState\n ) => void;\n onSwipeUp?: (gestureState: PanResponderGestureState) => void;\n onSwipeDown?: (gestureState: PanResponderGestureState) => void;\n onSwipeLeft?: (gestureState: PanResponderGestureState) => void;\n onSwipeRight?: (gestureState: PanResponderGestureState) => void;\n}\n"]} \ No newline at end of file +{"version":3,"sources":["index.ts"],"names":["SwipeDirection"],"mappings":"AAOA,WAAYA,cAAZ;;WAAYA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;AAAAA,EAAAA,c;GAAAA,c,KAAAA,c","sourcesContent":["import {\n Animated,\n GestureResponderEvent,\n PanResponderGestureState,\n ViewProps,\n} from 'react-native';\n\nexport enum SwipeDirection {\n SWIPE_UP = 'SWIPE_UP',\n SWIPE_DOWN = 'SWIPE_DOWN',\n SWIPE_LEFT = 'SWIPE_LEFT',\n SWIPE_RIGHT = 'SWIPE_RIGHT',\n}\n\nexport interface ZoomableViewEvent {\n zoomLevel: number;\n offsetX: number;\n offsetY: number;\n originalHeight: number;\n originalWidth: number;\n originalPageX: number;\n originalPageY: number;\n}\n\nexport interface ReactNativeZoomableViewProps extends ViewProps {\n // options\n zoomEnabled?: boolean;\n panEnabled?: boolean;\n initialZoom?: number;\n initialOffsetX?: number;\n initialOffsetY?: number;\n contentWidth?: number;\n contentHeight?: number;\n panBoundaryPadding?: number;\n maxZoom?: number;\n minZoom?: number;\n doubleTapDelay?: number;\n doubleTapZoomToCenter?: boolean;\n bindToBorders?: boolean;\n zoomStep?: number;\n pinchToZoomInSensitivity?: number;\n pinchToZoomOutSensitivity?: number;\n movementSensibility?: number;\n longPressDuration?: number;\n visualTouchFeedbackEnabled?: boolean;\n disablePanOnInitialZoom?: boolean;\n\n // Zoom animated value ref\n zoomAnimatedValue?: Animated.Value;\n panAnimatedValueXY?: Animated.ValueXY;\n\n // debug\n debug?: boolean;\n\n // callbacks\n onTransform?: (zoomableViewEventObject: ZoomableViewEvent) => void;\n onSingleTap?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapBefore?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onDoubleTapAfter?: (\n event: GestureResponderEvent,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onShiftingBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShiftingEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomBefore?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean | undefined;\n onZoomAfter?: (\n event: GestureResponderEvent | null,\n gestureState: PanResponderGestureState | null,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onZoomEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onLongPress?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onStartShouldSetPanResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent,\n baseComponentResult: boolean\n ) => boolean;\n onPanResponderGrant?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderEnd?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderMove?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onPanResponderTerminate?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => void;\n onPanResponderTerminationRequest?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onShouldBlockNativeResponder?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState,\n zoomableViewEventObject: ZoomableViewEvent\n ) => boolean;\n onStartShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onMoveShouldSetPanResponderCapture?: (\n event: GestureResponderEvent,\n gestureState: PanResponderGestureState\n ) => boolean;\n onStaticPinPress?: (event: GestureResponderEvent) => void;\n onStaticPinLongPress?: (event: GestureResponderEvent) => void;\n staticPinPosition?: Vec2D;\n staticPinIcon?: React.ReactElement;\n onStaticPinPositionChange?: (position: Vec2D) => void;\n onStaticPinPositionMove?: (position: Vec2D) => void;\n animatePin: boolean;\n pinProps?: ViewProps;\n disableMomentum?: boolean;\n}\n\nexport interface Vec2D {\n x: number;\n y: number;\n}\n\nexport interface Size2D {\n width: number;\n height: number;\n}\n\nexport interface TouchPoint extends Vec2D {\n id: string;\n isSecondTap?: boolean;\n}\n\nexport interface ReactNativeZoomableViewState {\n touches?: TouchPoint[];\n originalWidth: number;\n originalHeight: number;\n originalPageX: number;\n originalPageY: number;\n debugPoints?: undefined | Vec2D[];\n pinSize: Size2D;\n}\n\nexport interface ReactNativeZoomableViewWithGesturesProps\n extends ReactNativeZoomableViewProps {\n swipeLengthThreshold?: number;\n swipeVelocityThreshold?: number;\n swipeDirectionalThreshold?: number;\n swipeMinZoom?: number;\n swipeMaxZoom?: number;\n swipeDisabled?: boolean;\n onSwipe?: (\n swipeDirection: SwipeDirection,\n gestureState: PanResponderGestureState\n ) => void;\n onSwipeUp?: (gestureState: PanResponderGestureState) => void;\n onSwipeDown?: (gestureState: PanResponderGestureState) => void;\n onSwipeLeft?: (gestureState: PanResponderGestureState) => void;\n onSwipeRight?: (gestureState: PanResponderGestureState) => void;\n}\n"]} \ No newline at end of file diff --git a/lib/typescript/ReactNativeZoomableView.d.ts b/lib/typescript/ReactNativeZoomableView.d.ts index 50b26f3..0b44613 100644 --- a/lib/typescript/ReactNativeZoomableView.d.ts +++ b/lib/typescript/ReactNativeZoomableView.d.ts @@ -176,7 +176,7 @@ declare class ReactNativeZoomableView extends Component void; + moveStaticPinTo: (position: Vec2D, duration?: number) => void; private _staticPinPosition; private _updateStaticPin; private _addTouch; diff --git a/lib/typescript/typings/index.d.ts b/lib/typescript/typings/index.d.ts index 4b711f2..8d66deb 100644 --- a/lib/typescript/typings/index.d.ts +++ b/lib/typescript/typings/index.d.ts @@ -83,10 +83,10 @@ export interface TouchPoint extends Vec2D { } export interface ReactNativeZoomableViewState { touches?: TouchPoint[]; - originalWidth: number | null; - originalHeight: number | null; - originalPageX: number | null; - originalPageY: number | null; + originalWidth: number; + originalHeight: number; + originalPageX: number; + originalPageY: number; debugPoints?: undefined | Vec2D[]; pinSize: Size2D; } diff --git a/src/ReactNativeZoomableView.tsx b/src/ReactNativeZoomableView.tsx index a987104..6adf44b 100644 --- a/src/ReactNativeZoomableView.tsx +++ b/src/ReactNativeZoomableView.tsx @@ -38,10 +38,10 @@ import { } from './animations'; const initialState: ReactNativeZoomableViewState = { - originalWidth: null, - originalHeight: null, - originalPageX: null, - originalPageY: null, + originalWidth: 0, + originalHeight: 0, + originalPageX: 0, + originalPageY: 0, pinSize: { width: 0, height: 0 }, }; @@ -695,8 +695,6 @@ class ReactNativeZoomableView extends Component< const gestureCenterPoint = calcGestureCenterPoint(e, gestureState); if (!gestureCenterPoint) return; - if (this.state.originalPageX == null) return; - if (this.state.originalPageY == null) return; let zoomCenter = { x: gestureCenterPoint.x - this.state.originalPageX, @@ -773,8 +771,6 @@ class ReactNativeZoomableView extends Component< ) { const { touches } = gestureResponderEvent.nativeEvent; const { originalPageY, originalPageX } = this.state; - if (originalPageX == null) return; - if (originalPageY == null) return; this.setState({ debugPoints: [ @@ -911,7 +907,7 @@ class ReactNativeZoomableView extends Component< delete this.singleTapTimeoutId; delete this.doubleTapFirstTap; this._handleDoubleTap(e); - } else if (this.state.originalPageX && this.state.originalPageY) { + } else { this.doubleTapFirstTapReleaseTimestamp = now; this.doubleTapFirstTap = { id: now.toString(), @@ -950,7 +946,7 @@ class ReactNativeZoomableView extends Component< } }; - moveStaticPinTo = (position: Vec2D) => { + moveStaticPinTo = (position: Vec2D, duration?: number) => { const { originalWidth, originalHeight } = this.state; const { staticPinPosition, contentWidth, contentHeight } = this.props; @@ -965,7 +961,15 @@ class ReactNativeZoomableView extends Component< this.offsetX = contentWidth / 2 - position.x + pinX / this.zoomLevel; this.offsetY = contentHeight / 2 - position.y + pinY / this.zoomLevel; - this.panAnim.setValue({ x: this.offsetX, y: this.offsetY }); + if (duration) { + Animated.timing(this.panAnim, { + toValue: { x: this.offsetX, y: this.offsetY }, + useNativeDriver: true, + duration, + }).start(); + } else { + this.panAnim.setValue({ x: this.offsetX, y: this.offsetY }); + } }; private _staticPinPosition = () => { @@ -1023,8 +1027,6 @@ class ReactNativeZoomableView extends Component< if (nextZoomStep == null) return; const { originalPageX, originalPageY } = this.state; - if (originalPageX == null) return; - if (originalPageY == null) return; // define new zoom position coordinates const zoomPositionCoordinates = { @@ -1087,8 +1089,6 @@ class ReactNativeZoomableView extends Component< */ _zoomToLocation(x: number, y: number, newZoomLevel: number) { if (!this.props.zoomEnabled) return; - if (this.state.originalWidth == null) return; - if (this.state.originalHeight == null) return; this.props.onZoomBefore?.(null, null, this._getZoomableViewEventObject()); @@ -1100,8 +1100,6 @@ class ReactNativeZoomableView extends Component< // because here panAnim is being calculated in js. // However the jittering should mostly occur in simulator. const listenerId = this.zoomAnim.addListener(({ value: newScale }) => { - if (this.state.originalWidth == null) return; - if (this.state.originalHeight == null) return; this.panAnim.setValue({ x: calcNewScaledOffsetForZoomCentering( this.offsetX, diff --git a/src/typings/index.ts b/src/typings/index.ts index f9a7409..2232622 100644 --- a/src/typings/index.ts +++ b/src/typings/index.ts @@ -173,10 +173,10 @@ export interface TouchPoint extends Vec2D { export interface ReactNativeZoomableViewState { touches?: TouchPoint[]; - originalWidth: number | null; - originalHeight: number | null; - originalPageX: number | null; - originalPageY: number | null; + originalWidth: number; + originalHeight: number; + originalPageX: number; + originalPageY: number; debugPoints?: undefined | Vec2D[]; pinSize: Size2D; }