openspacelabs / react-native-zoomable-view

A view component for react-native with pinch to zoom, tap to move and double tap to zoom capability.
MIT License
189 stars 57 forks source link

zoomAnim value seems to be incorrect when device orientation is changed #80

Open nparoski opened 6 months ago

nparoski commented 6 months ago

This package has been working pretty good but I have problems with scaling when screen orientation is changed.

I am trying to scale image by width and always by default zoom farthest away to fit image from left edge of screen to right edge of screen.

I've looked at some of source code and looks like in ComponentDidUpdate this.zoomLevel = initialZoom; changes correctly when orientation is changed but in render method zoomAnim stays at previous scale.

Here's minimal code example:

import { Image, useWindowDimensions, Animated } from "react-native";
import { ReactNativeZoomableView } from "@openspacelabs/react-native-zoomable-view";

export const App = () => {
  const Dimensions = useWindowDimensions();

  return (
    <ReactNativeZoomableView
      minZoom={Dimensions.width / 1920}
      initialZoom={Dimensions.width / 1920}
      contentWidth={1920}
      contentHeight={1080}
    >
      <Image
        source={{
          uri: "https://i.pinimg.com/originals/71/9e/80/719e80760999b4c355a723224120eb07.png",
        }}
        width={1920}
        height={1080}
      />
    </ReactNativeZoomableView>
  );
};

Video example of what is currently happening:

Screencast from 12-22-2023 09:39:53 AM.webm

I am pretty certain that component needs to be rerendered on orientation change or zoomAnim change, I've tried patching this in my code base but It have pretty annoying delay:

Patch example:

import { Image, useWindowDimensions, Animated } from "react-native";
import { ReactNativeZoomableView } from "@openspacelabs/react-native-zoomable-view";
import * as ScreenOrientation from "expo-screen-orientation";

export const App = () => {
  const Dimensions = useWindowDimensions();
  const [forceRerender,setForceRerender] = useState<boolean>(false)

  useEffect(() => {
    const eventSub = ScreenOrientation.addOrientationChangeListener((event) => {
      setForceRerender(!forceRerender);
    });

    return () => {
      ScreenOrientation.removeOrientationChangeListener(eventSub);
    };
  }, []);

  return (
    <ReactNativeZoomableView
      minZoom={Dimensions.width / 1920}
      initialZoom={Dimensions.width / 1920}
      contentWidth={1920}
      contentHeight={1080}
      key={forceRerender ? Math.random() : Math.random()}
    >
      <Image
        source={{
          uri: "https://i.pinimg.com/originals/71/9e/80/719e80760999b4c355a723224120eb07.png",
        }}
        width={1920}
        height={1080}
      />
    </ReactNativeZoomableView>
  );
};

Video of patch preview Screencast from 12-22-2023 10:03:19 AM.webm

As you can see there is pretty annoying delay when changing orientation from portrait to landscape and from landscape to portrait, especially because first screen orientation changes, then image rotates, then image is zoomed and at last component is forceRerenderd making it scale properly but at expense of slow and choppy UI updates.