Giter Site home page Giter Site logo

pavelbabenko / react-native-awesome-gallery Goto Github PK

View Code? Open in Web Editor NEW
385.0 6.0 45.0 65.56 MB

Performant, native-like, and well-customizable gallery for React Native.

License: MIT License

JavaScript 5.77% TypeScript 94.23%
react-native reanimated2 image-viewer pinch-to-zoom ios android react image-gallery lightbox expo

react-native-awesome-gallery's Introduction

npm version

Support

If you love using React Native Awesome Gallery and would like to show your appreciation, you can support the project by buying me a coffee. Your support helps me keep the project alive and continuously improving. Every little bit counts!

"Buy Me A Coffee"

React Native Awesome Gallery

Photos gallery powered by Reanimated v2 and react-native-gesture-handler

Basic usage

With toolbar

Loop

Gallery basic usage Gallery with toolbar Gallery loop

Supported features

  • Zoom to scale
  • Double tap to scale
  • Native iOS feeling (rubber effect, decay animation on pan gesture)
  • RTL support
  • Fully customizable
  • Both orientations (portrait + landscape)
  • Infinite list
  • Supports both iOS and Android.

Installation

Note: Starting from v0.3.6 using Reanimated v3 is required

First you have to follow installation instructions of Reanimated v3 and react-native-gesture-handler

yarn add react-native-awesome-gallery

Expo is supported since SDK 40. More information here

Usage

Check out an example folder for example with Expo Image

import Gallery from 'react-native-awesome-gallery';

// ...

const images = ['https://image1', 'https://image2'];

return (
  <Gallery
    data={images}
    onIndexChange={(newIndex) => {
      console.log(newIndex);
    }}
  />
);

Props

Prop Description Type Default
data Array of items to render T[] undefined
renderItem? Callback func which can be used to render custom image component, e.g FastImage. NOTE: You have to call setImageDimensions({width, height}) parameter after image is loaded (renderItemInfo: {item: T, index: number, setImageDimensions: Function}) => React.ReactElement undefined
keyExtractor? Callback func which provides unique keys for items (item: T, index: number) => string or number Takes id or key or _id from Item, otherwise puts Item as key
initialIndex? The initial image index number 0
onIndexChange? Is called when index of active item is changed (newIndex: number) => void undefined
numToRender? Amount of items rendered in gallery simultaneously number 5
emptySpaceWidth? Width of empty space between items number 30
doubleTapScale? Image scale when double tap is fired number 3
doubleTapInterval? Time in milliseconds between single and double tap events number 500
maxScale? Maximum scale user can set with gesture number 6
pinchEnabled? Is pinch gesture enabled boolean true
doubleTapEnabled? Is double tap enabled boolean true
disableTransitionOnScaledImage? Disables transition to next/previous image when scale > 1 boolean false
hideAdjacentImagesOnScaledImage? Hides next and previous images when scale > 1 boolean false
disableVerticalSwipe? Disables vertical swipe when scale == 1 boolean false
disableSwipeUp? Disables swipe up when scale == 1 boolean false
loop? Allows user to swipe infinitely. Works when data.length > 1 boolean false
onScaleChange? Is called when scale is changed (scale: number) => void undefined
onScaleChangeRange? Shows range of scale in which onScaleChange is called {start: number, end: number} undefined
containerDimensions? Dimensions object for the View that wraps gallery. {width: number, height: number} value returned from useWindowDimensions() hook.
style? Style of container ViewStyle undefined

Events

Prop Description Type
onSwipeToClose Fired when user swiped to top/bottom Function
onTap Fired when user tap on image Function
onDoubleTap Fired when user double tap on image Function
onLongPress Fired when long press is detected Function
onScaleStart Fired when pinch gesture starts Function
onScaleEnd(scale: number) Fired when pinch gesture ends. Use case: add haptic feedback when user finished gesture with scale > maxScale or scale < 1 Function
onPanStart Fired when pan gesture starts Function

Methods

import Gallery, { GalleryRef } from 'react-native-awesome-gallery';

// ...

const ref = useRef<GalleryRef>(null);
Prop Description Type
setIndex Sets active index (newIndex: number, animated?: boolean) => void
reset Resets scale, translation (animated?: boolean) => void

License

MIT

react-native-awesome-gallery's People

Contributors

alantoa avatar baronha avatar felippepuhle avatar kanzitelli avatar mtflud avatar pavelbabenko avatar rozhkovs avatar trozee avatar vincent-azumuta avatar vonovak avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

react-native-awesome-gallery's Issues

^0.3.8 - Interactions not working into a modal component

Hey!
First, thanks for your work, it seems to be an awesome library.

I'm working on an react native application (0.72.x) and I need to use your "Gallery" or "AwesomeGallery" into a modal, but I can't do any interactions on it.

I'm using react native gesture handler ^2.11.0, and react native reanimated ^3.6.1, and I can say that's animated component works on my custom modal, but not on your component.

I tried to copy/paste your example, but It's the same.

The head of my custom modal component:

<Modal
            animationType="none"
            transparent={true}
            visible={visible}
            onDismiss={onPressToCloseModal}
            style={{width: '100%', flex: 1}}
        >
            <Pressable
                testID="modal_overlay"
                onPress={onPressToCloseModal}
                style={styles.wrapper}
            >
                <MotiView
                    state={animationState}
                    from={{translateY: height}}
                    onDidAnimate={closeOnDidAnimate}
                    style={[styles.wrapper, {backgroundColor: 'transparent'}]}
                >
                    <Pressable
                        onLayout={onLayoutModalContent}
                        style={styles.container}
                    >
                        {children}
                    </Pressable>
                </MotiView>
            </Pressable>
        </Modal>

There isn't any position absolute or anything related to position.
Any fix about this one ?

Thanks!

[Question] Is it possible to only use lightbox/carousel mode (without list gallery)?

Hey, i'm considering using this package in my project. I need to display a carousel of images, with swiping left/right and pinching for zooming.
I already have the actual gallery, using FlashList because i need it to be masonry-style.
So i was wondering if i can open the carousel view of this package directly by clicking an item in my masonry gallery.

btw the package seems nice! Good work.

Not working

Inside Modal its not working

Please kindly help

Resizable image

Thanks for the great library.

  • I was wondering if the Resizable image could be exposed in a reusable way.

Event "onSwipeToClose" is not working

I am using the library for the image zoom feature and am thankful to the authors that they build it. But I am not able to get work "onSwipeToClose" event but all other events are working for me. I am using it as below. Any help will be appreciated thanks! @pavelbabenko @alantoa

<CustomModal isModalVisible={openZoomViewer} backdropOpacity={1}> <Gallery data={image} hideAdjacentImagesOnScaledImage={true} disableSwipeUp={true} renderItem={renderItem} onSwipeToClose={closeZoomViewer} onDoubleTap={closeZoomViewer} onIndexChange={(newIndex) => { console.log(newIndex); }} style={{ alignSelf: 'center' }} /> </CustomModal>

Swiping Transition

Hello, this package is awesome. ฤฑ want to add opacity transition while swipe to close. ฤฑ tried something but the changes ฤฑ made doesn't affect the code. How can ฤฑ modify the package code ?

Can not zoom, swipe list images when using Modal

react-native: 0.65.1
react-native-awessome-gallery: 0.2.6
react-native-reanimated: 2.2.3

Code

<Modal visible={true}>
	<Gallery
		ref={galleryRef}
		data={props.imageUrls}
		maxScale={10}
		initialIndex={props.defaultIndex}
		onIndexChange={setSelectedImage}
	/>
</Modal>

Example shared element transition

Hello, thank you for this amazing gallery!
One thing that I've noticed is that when running the example that you provided, it doesn't seem to have shared element transition when opening and closing. Is there any example on shared element transition like in the gif that is on the main page of this repository?

Thank you for this library!

Simulator.Screen.Recording.-.iPhone.14.Pro.-.2023-12-15.at.00.52.06.mp4

does not appear to work on android

Hello, thanks for the lib

I gave it a try on and ios and android (version 10) devices and I'd like to report that while it works nice on ios, it does not work on Android.

The issue can be reproduced with the readme sample.

On Android, double-tapping to zoom works, but swiping horizontally to change pictures does not work, and pinch to zoom does not work either.

using RN 64 stable and reanimated 2

Maybe this should be mentioned in the readme. Thanks!

^0.3.8 Wrong positions when more than 1 image

Hey again!

I'm not using expo image, I don't know if it can be related, but when I've got more than 1 image into my data, it's not showing correctly the gallery content.

Capture d'รฉcran 2023-12-22 161233

My component:

<GestureHandlerRootView>
                <AwesomeGallery
                    data={form.images.map(image => {
                        return {
                            uri: `data:image/png;base64,${fromByteArray(
                                image
                            )}`,
                        }
                    })}
                    keyExtractor={item => item.uri}
                    renderItem={renderItem}
                    initialIndex={0}
                    numToRender={3}
                    doubleTapInterval={150}
                    onIndexChange={() => {
                        //
                    }}
                    onSwipeToClose={() => {
                        //
                        setShowGallery(false)
                    }}
                    onTap={() => {
                        //
                    }}
                    loop
                    onScaleEnd={scale => {
                        if (scale < 0.8) {
                            //
                        }
                    }}
                />
</GestureHandlerRootView>

I'm using the same boilerplate as the example provided, tried a lot of params (played with loop, numToRender, onLoadEnd, onLoad, and more) but same result.
But it's working perfectly when there is only 1 image.

Capture d'รฉcran 2023-12-22 162512

I'm probably missing something, I'm sorry about it...
Have a nice day!

Replace 2 loops by one

In the snapPoint function we have two loops - that should find the minimum delta. This function looks good, but we can change it to one loop, with the same functionality.
From:

const deltas = points.map((p) => Math.abs(point - p));
const minDelta = Math.min.apply(null, deltas);

To:

let minDelta = Number.MAX_VALUE;
for (let i = 0; i < points.length; i++) {
  const newDelta = Math.abs(point - points[i]);
  if (newDelta < minDelta) {
    minDelta = newDelta;
  }
}

Thank your for being a huge part of Memos

there's no other way for contacting you @pavelbabenko
but I wanted to Thank you for being a very important part of memos which is a cloud storage for storing your best photos/videos, I started implementing the Gallery from scratch and after 4 days I slowly realized that It was a heavy task to handle gestures for swiping, zooming, pinching and momentum when moving while zooming all together without having huge performance issues. and that library was a really good abstraction that gave me the ability for adding other functionalities like time, share, set as album cover, delete, download and custom video player.

Links:
Repo
Google Play Store

react-native-reanimated v3 support

Hey, thanks for a great package. Do you plan to support react-native-reanimated v3? Currently, npm install fails because of ^2.x.x in peer dependencies.

Question: can I get access to current scale without use events?

I'm using a renderItem and I added description, but I wanna hide the text when scale is different to 1.

I'm using onScaleStart and onScaleEnd and its working, but when I trigger a doubleTap, I donยดt have any way to validate inside this event that the scale is 1 or not.

Bug: When zoom in on the long pic, tap while scrolling

Hi, I really like this component, but i'm very busy right now, or I'll submit it once pr.

Description

I'm binding onTap this method, when zoom in on the long pic, tap while scrolling, the onTap event is triggered by the scroll event.

Code

<AwesomeGallery
    data={params?.images.map((uri) => ({ uri }))}
    keyExtractor={(_, i) => `${i}`}
    renderItem={({ index, item, setImageDimensions }) =>
      renderItem({ index, item, setImageDimensions })
    }
    initialIndex={params.index}
    onIndexChange={onIndexChange}
    onSwipeToClose={goBack}
    onTap={goBack}
  />

Video demo:

IMG_4029.MOV

So we can ? & I hope ๐Ÿ’— :

Turn off the onTap event in the scrool event?
(or)
Stop scrolling when tap?

Thanks!!!

๏ฟฝ

Removing an image causes lockup

I'm using the following dependencies:

"dependencies": {
    "react": "17.0.2",
    "react-native": "0.68.1",
    "react-native-awesome-gallery": "0.3.5",
    "react-native-gesture-handler": "^2.4.1",
    "react-native-reanimated": "^2.8.0"
  },

Once an image is removed from the array, gestures stop being recognised. If you change the removed image position from 0 to say 2, it only locks up when you scroll to index 2 in the image array.

Seems to be a reoccurrence of #19.

import React, {useState} from 'react';
import {Button, View} from 'react-native';
import AwesomeGallery from 'react-native-awesome-gallery';
import {GestureHandlerRootView} from 'react-native-gesture-handler';

const IMAGE_DATA = [
  'https://cdn.pixabay.com/photo/2017/02/20/18/03/cat-2083492_960_720.jpg',
  'https://cdn.pixabay.com/photo/2014/04/13/20/49/cat-323262__340.jpg',
  'https://cdn.pixabay.com/photo/2015/11/16/14/43/cat-1045782__340.jpg',
  'https://cdn.pixabay.com/photo/2021/10/19/10/56/cat-6723256__340.jpg',
];

const App = () => {
  const [images, setImages] = useState(IMAGE_DATA);

  const removeImage = () => {
    setImages(i => i.slice(1));
  };

  return (
    <GestureHandlerRootView style={{flex: 1, backgroundColor: 'red'}}>
      <AwesomeGallery
        data={images}
        keyExtractor={(item, index) => item}
        doubleTapInterval={150}
        onTap={() => console.log('tap')}
      />
      <View style={{position: 'absolute', top: 0, left: 0}}>
        <Button onPress={removeImage} title="REMOVE"></Button>
      </View>
    </GestureHandlerRootView>
  );
};

export default App;

Does not work with a single image

When loading a Gallery with a single image, you are still able to swipe to a next image (which does not exist) and then breaks the navigator (unable to swipe back to the first and only image).

Dynamically changed image data.

Hi, when I try to delete one of the image in the data array, I am still able to swipe to that index and it is black page. It froze then. I am guessing it is because the length of the array is not updated, any fix? Thanks!

Bug: gallery does not work if using containerDimensions prop value changes

We are working on responsive app that supports different layouts for mobiles and tablets and portrait/landscape orientations. On iPads we present gallery in a native navigation modal, which is not a full screen size, so we have to use onLayout callback of gallery container and containerDimensions property:

containerDimensions={{ width: layout.width, height: layout.height }}

This results in incorrect behaviour when containerDimensions changes, for example when changing orientation. I looked around in source code and was able to fix it by simply adding dimensions.width to useEffect dependencies:

useEffect(() => {
    translateX.value = index * -(dimensions.width + emptySpaceWidth);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [windowDimensions, dimensions.width]);
useEffect(() => {
  if (index >= data.length) {
    const newIndex = data.length - 1;
    setIndex(newIndex);
    currentIndex.value = newIndex;
    translateX.value = newIndex * -(dimensions.width + emptySpaceWidth);
  }
  // eslint-disable-next-line react-hooks/exhaustive-deps
}, [data?.length, dimensions.width]);

So it looks like it is just missing dependencies, but I was wondering why it specifically has eslint-disable-next-line react-hooks/exhaustive-deps rule which would have helped to avoid the issue in the first place.

Remove unnecessary checks

Both Tap and LongPress gestures have unnecessary checks. For example, tapGesture is disabled when onTap is not provided, so we can add a non-null assertion without checking its value. Similar for rest gestures.

Changes in the tapGesture:

.onEnd(() => {
  'worklet';
  if (!isActive.value) return;
  if (onTap && !interruptedScroll.value) {
    runOnJS(onTap)();
  }
  interruptedScroll.value = false;
});


.onEnd(() => {
  'worklet';
  if (!isActive.value) return;
  if (!interruptedScroll.value) {
    runOnJS(onTap!)();
  }
  interruptedScroll.value = false;
});

In the doubleTapGesture:

.onEnd(({ x, y, numberOfPointers }) => {
  'worklet';
  if (!isActive.value) return;
  if (numberOfPointers !== 1) return;
  if (onTap && interruptedScroll.value) {
    interruptedScroll.value = false;
    if (onTap) {
      runOnJS(onTap)();
    }
    return;
  }
  if (onDoubleTap) {
    runOnJS(onDoubleTap)();
  }


.onEnd(({ x, y, numberOfPointers }) => {
  'worklet';
  if (!isActive.value) return;
  if (numberOfPointers !== 1) return;
  if (onTap && interruptedScroll.value) {
    interruptedScroll.value = false;
    runOnJS(onTap)();
    return;
  }
  if (onDoubleTap) {
    runOnJS(onDoubleTap)();
  }

And in the longPress:

const longPressGesture = Gesture.LongPress()
  .enabled(!!onLongPress)
  .maxDistance(10)
  .onStart(() => {
    'worklet';
    if (interruptedScroll.value) {
      interruptedScroll.value = false;
      return;
    }
    if (onLongPress) {
      runOnJS(onLongPress)();
    }
  });


const longPressGesture = Gesture.LongPress()
  .enabled(!!onLongPress)
  .maxDistance(10)
  .onStart(() => {
    'worklet';
    if (interruptedScroll.value) {
      interruptedScroll.value = false;
      return;
    }
    runOnJS(onLongPress)();
  });

[Feature Request] Reset Transforms API

Hi! Thanks for this library. It works very well within our project. I've had a few requests from our product team to enable support for resetting transforms (scale) when certain user events occur, such as an orientation change.

It would be extremely helpful if there was a ref API or other mechanism for resetting transforms on demand.

Thanks for taking a look!

Can not use pan gesture on tall images

you can not move up or down in really tall images, its like the spring animation does not allow you to do.

WhatsApp.Video.2021-08-30.at.9.06.06.PM.mp4

Wrong focal values on zoom on both platforms

Hi,

While double tapping to zoom or pinch to zoom, on release the focal is being reset at the top part of the image. This happens on both Android and iOS using a 1920x1080 image.

[email protected] on Paper,
gesture [email protected]
[email protected]
[email protected]

The only solution I could find is to set the height on useVector:

    const originalLayout = useVector(width, height);
    const layout = useVector(width, height);

When height is set to 0, 1st tap on scarecrow, 2nd tap on pipboy, 3rd tap on chair resets the focal between scarecrow and pipboy:

RPReplay_Final1713773021_720p.mp4

When height is set from props everything is fine:

RPReplay_Final1713772999.mp4

renderItem, I already know the image dimensions from image object:

const renderItem = ({
  item,
  setImageDimensions
}: RenderItemInfo<{
  blurhash?: string;
  height: number;
  thumbnailSource: string;
  url: string;
  width: number;
}>) => {
  return (
    <CachedImage
      blurhash={item.blurhash}
      images={item.url}
      onLoad={() => {
        setImageDimensions({ width: item.width, height: item.height });
      }}
      resizeMode="contain"
      style={StyleSheet.absoluteFillObject}
    />
  );
};

translateX offset, image disappear on pan

Hi there,

I have the strangest issue to open, first time for me.

On a single iOS device, when opening the gallery, we have a bigger and bigger left margin (or translationY) as we open the gallery to an initialIndex higher and higher:

  1. Open the first index in the gallery: work as expected
  2. Opening the 10 index: we begin to see a substantial margin on the left
  3. Opening index 100, the image displayed is the one before the current image.

React Native 0.70.6
Awesome gallery 0.3.5
OS: iOS only (no issue on android)
Device model: iPhone 8 plus, iOS 16.3.1,

The weirdest thing is that on another identicial phone model, identical app version and clean install, we don't have the issue at all.
So I'm fishing here as I didn't see a similar issue on this repo before, without a reproduction, to check wheter if you may have an idea about the issue.

    "react-native-gesture-handler": "2.12.0",
    "react-native-reanimated": "^2.17.0",

Take care,

RenderItem with FastImage failed

Here is my code:
const customRenderImage = ({item, setImageDimensions}) => { return ( <FastImage onLoad={e => { const {height: h, width: w} = e.nativeEvent.source; setImageDimensions({height: h, width: w}); }} source={{uri: item.uri}} resizeMode={FastImage.resizeMode.contain} style={StyleSheet.absoluteFillObject} /> ); };

My item looks like {
key = "bf9e684f-495e-4427-b170-82504a006eb7",
uri = "file://file:///Users/zijianzhang/Library/Developer/CoreSimulator/Devices/685BDAED-7EDA-4922-A082-56EA73788452/data/Containers/Data/Application/805F046E-2CAC-4C1B-9824-39B44CDB4EA3/tmp/IMG_0111.HEIC"}

Got error JSON value '{
key = "bf9e684f-495e-4427-b170-82504a006eb7";
uri = "file://file:///Users/zijianzhang/Library/Developer/CoreSimulator/Devices/685BDAED-7EDA-4922-A082-56EA73788452/data/Containers/Data/Application/805F046E-2CAC-4C1B-9824-39B44CDB4EA3/tmp/IMG_0111.HEIC";
}' of type NSMutableDictionary cannot be converted to NSString.

Even trying implement the same code as defaultRenderItem does not work and generate the same error. Is there anything I miss? Thank you!

[Discussion] Library feedback

Hey @pavelbabenko
Thank you for a great library. I am happy, that you are maintaining this library and I can use this library in my project.
While I was developing, I noticed few things:

  • we can make a transition to the next item, once the image scale is greater than 1. I checked, how it looks like in the other apps (Twitter, WhatsApp, messenger )and the image scale needs to be 1 to go to the next page. When the image scale is greater than one (image is zoomed) it sticks to the edge (so offset is clamped to the 0, when the image touch the edge)

  • it would be nice to have a prop, which could block a vertical gesture when the scale of the image is 1 (when an image is not resized). I did it locally in my project so I could make a PR for that feature. Before I do it, please let me know, if you would like to handle it in your library.

  • I also implemented setPage locally and it looks like below :

    useImperativeHandle(ref, () => ({
      setPage(index: number) {
        setIndex(index);
        currentIndex.value = index;
        translateX.value = index * -(dimensions.width + emptySpaceWidth);
      },
    }));

ant then you can use it as follow:
galleryRef.current.setPage(index);

And I am not sure if it is a good solution. I was trying to move the below code to the parent component

const [index, setIndex] = useState(initialIndex);

But it did not work very well. Also, It would be nice to have this kind of functionality inside the library

WDYT about my propositions ?

Bug: Pinch to zoom and move are not working together

Platform: iOS / Android
Version of react-native-awesome-gallery: 0.2.0
Steps to reproduce: Pinch to zoom with 2 fingers. Try to move/drag image with two fingers or one finger.
Current behavour: Image will centered in the middle all the time when I use renderItem prop, you can't move/drag it around while it zoomed. You can't view the top and bottom part of the image.
Expected behavoir: While zoomed in I can move the screen and view the top and bottom part of the image.

Thank you!

how to retrain actual image quality on zoom image

i have hd image like size is 1 to 2 mb but on zooming its not visible clear how can i retreive actual image quality but in web its showing actual image quality on zoom

my code:-

import React, {useState, useEffect} from 'react';
import {View, Text, TouchableOpacity} from 'react-native';
import Gallery from 'react-native-awesome-gallery';

const SpeechToTextComponent = () => {
  const [index, setIndex] = useState(0);
  const images = [
    'https://d22pqt2na9k0l.cloudfront.net/image/2023/11/11/kka/kol/08/10nov23_pk_kka_kol_8_r1_20231116062003.jpg',
    'https://d22pqt2na9k0l.cloudfront.net/image/2023/11/11/kka/kol/08/10nov23_pk_kka_kol_8_r1_20231116062003.jpg',
    'https://d22pqt2na9k0l.cloudfront.net/image/2023/11/11/kka/kol/08/10nov23_pk_kka_kol_8_r1_20231116062003.jpg',
    'https://d22pqt2na9k0l.cloudfront.net/image/2023/11/11/kka/kol/08/10nov23_pk_kka_kol_8_r1_20231116062003.jpg',
  ];
  const [scale, setScale] = useState(1); // Initial scale

  const handleScaleChange = newScale => {
    console.log("newScale", newScale);
    // Update the scale state
    setScale(newScale);
  };

  return (
    <View>
      {/* <PrabhatKharbharLogoForLightMode height={130} width={270}/> */}
      <Gallery
        data={images}
        onIndexChange={newIndex => {
          console.log(newIndex);
          setIndex(newIndex);
        }}
        key={index?.toString()}
        disableTransitionOnScaledImage={true}
        hideAdjacentImagesOnScaledImage={true}
        onScaleChangeRange={({scale, width, height}) => {
          // Adjust width and height according to scale
          const adjustedWidth = width * scale;
          const adjustedHeight = height * scale;
    
          return {width: adjustedWidth, height: adjustedHeight};
        }}
      />
    </View>
  );
};

export default SpeechToTextComponent;

Infinite list?

The description of the library says that it supports an "Infinite list", but I can't figure out how to achieve that.
May someone explain, please?

Image snaps to horizontal center after scaling

Description

When performing any gesture to change the image scale, the image seems to always center itself horizontally after the gesture has ended. This is fine when scaling the image to be smaller than the container (scale < 1), but should not be happening when zooming in (scale > 1).

Right now this causes the "focus" to shift away from the point that was zoomed into after ending the gesture. For me this issue is happening on Android using the package versions listed below, I was not yet able to test it on an iOS device.

scaling.mp4

Minimal code example

export const ImageScreen = () => {
  const source = 'https://homepages.cae.wisc.edu/~ece533/images/cat.png';
  return <Gallery data={[source]} />;
}

Package versions

  • react-native: 0.64.0
  • react-native-gesture-handler: 1.10.3
  • react-native-reanimated: 2.1.0
  • react-native-awesome-gallery: 0.1.0 (also on 0.0.9)

Unable to run the example code, or use this module in my own app. Also, the sample code and /example code have different imports

Good day!

  1. Here is the sample code on the repo readme.
    import Gallery from 'react-native-awesome-gallery';
    vs the code in /example
    import AwesomeGallery, { GalleryRef, RenderItemInfo, } from 'react-native-awesome-gallery';
    Source: https://github.com/pavelbabenko/react-native-awesome-gallery/blob/main/example/src/screens/Photos.tsx#L16C1-L19C39

To find out which import is correct, I tried to run the /example code but I am unable to do so. Upon running yarn install and npx expo start in the example folder, I receive

(node:47203) [DEP_WEBPACK_DEV_SERVER_CONSTRUCTOR] DeprecationWarning: Using 'compiler' as the first argument is deprecated. Please use 'options' as the first argument and 'compiler' as the second argument.
(Use `node --trace-deprecation ...` to show where the warning was created)
(node:47203) [DEP_WEBPACK_DEV_SERVER_LISTEN] DeprecationWarning: 'listen' is deprecated. Please use the async 'start' or 'startCallback' method.
ERROR in ../src/index.tsx 1:0-67
Module not found: Error: Can't resolve '@babel/runtime/helpers/defineProperty' in '/Users/apoorvsm/Downloads/react-native-awesome-gallery-main 2/src'

ERROR in ../src/index.tsx 1:67-132
Module not found: Error: Can't resolve '@babel/runtime/helpers/slicedToArray' in '/Users/apoorvsm/Downloads/react-native-awesome-gallery-main 2/src'

ERROR in ../src/index.tsx 1:132-217
Module not found: Error: Can't resolve '@babel/runtime/helpers/objectWithoutProperties' in '/Users/apoorvsm/Downloads/react-native-awesome-gallery-main 2/src'

ERROR in ../src/index.tsx:28
Module not found: Can't resolve 'react-native-redash'
  26 | } from 'react-native-reanimated';
  27 | import { Gesture, GestureDetector } from 'react-native-gesture-handler';
> 28 | import { useVector } from 'react-native-redash';
  29 | import { clamp, withDecaySpring, withRubberBandClamp } from './utils';
  30 |
  31 | const rtl = I18nManager.isRTL;

web compiled with 4 errors

yarn add 'react-native-redash' doesn't resolve the issue. Neither does resetting cache, deleting node_modules, deleting watchman cache, etc. The IOS render fails with errors from @babel/runtime in a similar fashion.

Has anybody encountered this?

  1. I tried to use this library in my app, I installed the listed dependencies of this library. Here is my package.json
{
  "name": "Smilefie",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "android": "react-native run-android",
    "ios": "react-native run-ios",
    "lint": "eslint .",
    "start": "react-native start",
    "test": "jest",
    "build:ios": "react-native bundle --entry-file='index.js' --bundle-output='./ios/main.jsbundle' --dev=false  --platform='ios' --assets-dest ios"
  },
  "dependencies": {
    "@babel/plugin-proposal-export-namespace-from": "^7.18.9",
    "@react-native-community/masked-view": "^0.1.11",
    "@react-navigation/native": "^6.1.7",
    "@react-navigation/stack": "^6.3.17",
    "install": "^0.13.0",
    "react": "18.2.0",
    "react-native": "0.72.3",
    "react-native-app-info": "^0.0.6",
    "react-native-awesome-gallery": "^0.3.6",
    "react-native-camera": "^4.2.1",
    "react-native-fs": "^2.20.0",
    "react-native-gesture-handler": "^2.13.3",
    "react-native-reanimated": "^3.5.4",
    "react-native-safe-area-context": "^4.7.1",
    "react-native-screens": "^3.24.0",
    "react-native-vector-icons": "^10.0.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@babel/preset-env": "^7.20.0",
    "@babel/runtime": "^7.20.0",
    "@react-native/eslint-config": "^0.72.2",
    "@react-native/metro-config": "^0.72.9",
    "@tsconfig/react-native": "^3.0.0",
    "@types/react": "^18.0.24",
    "@types/react-test-renderer": "^18.0.0",
    "babel-jest": "^29.2.1",
    "eslint": "^8.19.0",
    "jest": "^29.2.1",
    "metro-react-native-babel-preset": "0.76.7",
    "prettier": "^2.4.1",
    "react-test-renderer": "18.2.0",
    "typescript": "4.8.4"
  },
  "engines": {
    "node": ">=16"
  }
}

However, upon navigating to the AwesomeGallery screen in my app, we see a black screen and no logs to help triage the issue. Would anyone be able to help diagnose and solve this issue?

I will help raise a PR for issue (1) to maintain code consistency between readme.md and /example once we are able to confirm the correct import.
Thanks!

Tap gestures not working

Hi, first of all, thanks for making the library, it's very handy.

I'm using 0.3.4, unfortunately tap and double tap gestures are not firing on either iOS or Android.

Example code:

 <Gallery
        disableTransitionOnScaledImage
        ref={galleryRef}
        data={images}
        onDoubleTap={() => {
          //doesn't work
          console.log('double tap');
        }}
        onTap={() => {
          //doesn't work
          console.log('tap');
        }}
         onScaleChange={() => {
          //works
          console.log('scale');
        }}
      />

Images rendering at lower resolution with SharedElement transition

Hello! Great work on this library, it's really helping me out a lot!

I have a problem/question, and I'm not sure if it's just my implementation or a limitation of the library.

It seems like images rendered in the gallery are low resolution.

I am using shared element transitions to do something like this:

Feed.tsx

<SharedElement id={`${href}`}>
  <MemoizedImage source={href} />
 </SharedElement>

Gallery.tsx

const renderItem = ({
  item,
  setImageDimensions,
}: RenderItemInfo<string>) => {
  return (
    <SharedElement id={`${item.href}`} style={StyleSheet.absoluteFillObject}>
      <Image
        source={item.href}
        contentFit="contain"
        contentPosition="center"
        priority="high"
        style={{StyleSheet.absoluteFillObject}}
        onLoad={(e: ImageLoadEventData) => {
          setImageDimensions({
            width,
            height,
          });
        }}
      />
    </SharedElement>
  );
};

export default function ImageScreen(props: ImageScreenProps) {
  const { goBack } = props.navigation;
  const { params } = props.route;
  const gallery = useRef<GalleryRef>(null);
  const data = useMemo(() => [params], [params]);

  return (
    <AwesomeGallery
      ref={gallery}
      data={data}
      renderItem={renderItem}
      doubleTapInterval={150}
      onSwipeToClose={goBack}
      coverScreen={true}
    />
  );
}

so, Feed renders small image thumbnails, and when you click on those thumbnails, it's transitioned to a full-screen modal-like view with AwesomeGallery.

my MemoizedImage is a wrapper around Expo-Image. When the image loads, I calculate a "scaled down" size for it (to render it in a post feed at thumbnail dimensions). i.e: if an image is 1000x1000px, I render it at 200x200px, for example.

However, when in the Gallery view, the image is the same resolution as the thumbnail - 200px - and so zooming in on the image, you do not see much detail.

Any tips on how I can fix this? I'd like the full-sized image in the "Gallery" view.

Add loading component

This gallery supports zoom which is fantastic and encourages loading large resolution images.

When the images are preloading after gallery opens, there is no indication that the gallery actually opened leading to poor user experience.

It would be great if we could inject a "loading" component.

That do you think please? Thanks!

Buggy behavior while changing from portrait to landscape on zoomed in images

While this is kind of hard to reproduce, it does happen. Looks like the library is having issues displaying an image after toggling between portrait and landscape while zoomed in. These are the reproduction steps that work consistently for me:

  • Create a react-native-awesome-gallery component with 2 or more images
  • Zoom in on an image and swipe to the other image while still zoomed in
  • Zoom in on this new image
  • Toggling between portrait and landscape
  • Zoom out of the image
  • Observe how images are overlapped
RPReplay_Final1655510195.mov

Any help would be greatly appreciated!

Bug: Android Device Rotation Breaks Paging

Platform: Android
Version of react-native: 0.64.1
Version of react-native-awesome-gallery: 0.2.2

Steps to reproduce:

  1. Create a gallery with 3 images.
  2. Page to the 2nd image.
  3. Rotate the device from portrait to landscape and back.

Current behavior: Scroll offset for the current "page" is incorrect, rendering multiple gallery items at once. Manually gesturing a swipe will recover the offset.

Expected behavior: Scroll offsets will update and maintain page positions based on the updated screen width/height after an orientation change.

This bug only occurs on Android. iOS behaves as expected.

Suggestion: Loop and onTap issue

Hello!
Thank you for the great library @pavelbabenko!

I really like the code inside and whole functionality, it works perfectly.
I would like to know: Do you have the possibility to implement a loop in Gallery?
I think it will be a great addition.

I also facing the issue when my single tap function calls even when I zoom in and zoom out.
Probably because of conflict PinchGestureHandler and TapGestureHandler between each other.
Can it be two separate actions?

Thanks!

Dynamically changed images array?

First of all, thank you for developing such a nice library. But I am wondering if this will support dynamically changed data. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.