intergalacticspacehighway / react-native-reanimated-zoom

Component for zooming react native views. 🔎
MIT License
315 stars 19 forks source link

Swipe down gesture possible? #15

Closed xmflsct closed 1 year ago

xmflsct commented 1 year ago

Love this library! Though in apps when images are opened in fullscreen, a common gesture to close or dismiss the view is swiping down. I tried to implement fling gesture using react-native-gesture-handler outside this component but failed. Other gesture recognition outside this library works fine like long press, but not fling.

Is there a possible to add a swipe down callback? Thanks!

intergalacticspacehighway commented 1 year ago

Hi @xmflsct, thanks for reporting. I was able to reproduce the issue. Can you try out https://github.com/intergalacticspacehighway/react-native-reanimated-zoom/pull/16 solution and let me know if it works for you? I can do a new release soon.

xmflsct commented 1 year ago

Thanks a lot! It works perfectly!

intergalacticspacehighway commented 1 year ago

Perfect! Released in 0.3.2. https://github.com/intergalacticspacehighway/react-native-reanimated-zoom/releases/tag/0.3.2

sregg commented 1 year ago

@xmflsct can you share your code for the swipe down to close gesture/animation?

xmflsct commented 1 year ago

@sregg See https://github.com/tooot-app/app/commit/da1ea314a4d9b22caa2a3d4769793d68ac838f68. But since when an image is zoomed, I don't want to capture the swipe down gesture which conflicts with panning down, I had to patch this library with a isZoomed state which currently is not exposed, https://github.com/tooot-app/app/commit/5c255ffa6d426cdce353e205cae347309325e478. @intergalacticspacehighway maybe a useful use case for another update? :)

sregg commented 1 year ago

Ah that'd be great. I'll try to push a PR. Thanks for sharing.

intergalacticspacehighway commented 1 year ago

@xmflsct Thanks, yeah good usecase.

I feel exposing isZoomed could be a bit confusing. It feels like something you can use to control the zoom, no?

What about exposing two callbacks onZoomBegin and onZoomEnd? I am already using this pattern internally to disable scroll in createZoomList when it's zoomed in.

sregg commented 1 year ago

That's exactly what I was implementing right now 😄

  useDerivedValue(() => {
    if (scale.value > 1 && !isZoomed.value) {
      isZoomed.value = true;
      if (zoomListContext) runOnJS(zoomListContext.onZoomBegin)();
      if (onZoomBegin) runOnJS(onZoomBegin)();
    } else if (scale.value === 1 && isZoomed.value) {
      isZoomed.value = false;
      if (zoomListContext) runOnJS(zoomListContext.onZoomEnd)();
      if (onZoomEnd) runOnJS(onZoomEnd)();
    }
  }, [zoomListContext, onZoomBegin, onZoomEnd]);

I'll push a PR in a sec.

sregg commented 1 year ago

Here's the patch diff if anyone wants to try before the PR:

diff --git a/node_modules/react-native-reanimated-zoom/lib/typescript/zoom.d.ts b/node_modules/react-native-reanimated-zoom/lib/typescript/zoom.d.ts
index 38fb6f1..5e44ebc 100644
--- a/node_modules/react-native-reanimated-zoom/lib/typescript/zoom.d.ts
+++ b/node_modules/react-native-reanimated-zoom/lib/typescript/zoom.d.ts
@@ -6,6 +6,8 @@ declare type Props = {
     minimumZoomScale?: number;
     maximumZoomScale?: number;
     simultaneousGesture?: GestureType;
+    onZoomBegin?: () => void;
+    onZoomEnd?: () => void;
 } & ViewProps;
 export declare function Zoom(props: Props): JSX.Element;
 export {};
diff --git a/node_modules/react-native-reanimated-zoom/src/zoom.tsx b/node_modules/react-native-reanimated-zoom/src/zoom.tsx
index e07b415..c96fbb4 100644
--- a/node_modules/react-native-reanimated-zoom/src/zoom.tsx
+++ b/node_modules/react-native-reanimated-zoom/src/zoom.tsx
@@ -20,6 +20,8 @@ type Props = {
   minimumZoomScale?: number;
   maximumZoomScale?: number;
   simultaneousGesture?: GestureType;
+  onZoomBegin?: () => void;
+  onZoomEnd?: () => void;
 } & ViewProps;

 export function Zoom(props: Props) {
@@ -29,6 +31,8 @@ export function Zoom(props: Props) {
     style: propStyle,
     onLayout,
     simultaneousGesture,
+    onZoomBegin,
+    onZoomEnd
   } = props;

   const zoomListContext = useContext(ZoomListContext);
@@ -224,11 +228,13 @@ export function Zoom(props: Props) {
     if (scale.value > 1 && !isZoomed.value) {
       isZoomed.value = true;
       if (zoomListContext) runOnJS(zoomListContext.onZoomBegin)();
+      if (onZoomBegin) runOnJS(onZoomBegin)();
     } else if (scale.value === 1 && isZoomed.value) {
       isZoomed.value = false;
       if (zoomListContext) runOnJS(zoomListContext.onZoomEnd)();
+      if (onZoomEnd) runOnJS(onZoomEnd)();
     }
-  }, [zoomListContext]);
+  }, [zoomListContext, onZoomBegin, onZoomEnd]);

   const style = useAnimatedStyle(() => {
     return {
sregg commented 1 year ago

Here's the PR: https://github.com/intergalacticspacehighway/react-native-reanimated-zoom/pull/17

intergalacticspacehighway commented 1 year ago

Thanks, @sregg ! Released in 0.3.3

sregg commented 1 year ago

Any idea how to animate the image being dragged down as the user flings down to close?

intergalacticspacehighway commented 1 year ago

@sregg you can use PanGesture handler for it.

sregg commented 1 year ago

Wouldn't it conflict with the pan gesture inside the Zoom component though?

intergalacticspacehighway commented 1 year ago

you mean if the image is zoomed in and the user starts panning, it should pause the zoom and let the outer pan takeover?

fukemy commented 8 months ago

Hi, can someone add an example? I want to implement swipe down to dismiss