Add custom AnimatedImage component
This also fixes the white flashing when loading images Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
This commit is contained in:
56
src/components/animatedImage.tsx
Normal file
56
src/components/animatedImage.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import React, { ComponentProps, useMemo } from 'react';
|
||||
import { Image } from 'react-native';
|
||||
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
|
||||
import Animated, {
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withSpring,
|
||||
} from 'react-native-reanimated';
|
||||
|
||||
const AnimatedImage = ({ ...props }: ComponentProps<typeof Image>) => {
|
||||
const scale = useSharedValue(1);
|
||||
const translateX = useSharedValue(0);
|
||||
const translateY = useSharedValue(0);
|
||||
|
||||
const animatedStyles = useAnimatedStyle(() => {
|
||||
return {
|
||||
transform: [
|
||||
{ translateX: translateX.value },
|
||||
{ translateY: translateY.value },
|
||||
{ scale: scale.value },
|
||||
],
|
||||
};
|
||||
});
|
||||
|
||||
const gesture = useMemo(
|
||||
() =>
|
||||
Gesture.Simultaneous(
|
||||
Gesture.Pinch()
|
||||
.onUpdate(event => {
|
||||
scale.value = event.scale;
|
||||
})
|
||||
.onFinalize(() => {
|
||||
scale.value = withSpring(1);
|
||||
}),
|
||||
Gesture.Pan()
|
||||
.minPointers(2)
|
||||
.onUpdate(event => {
|
||||
translateX.value = event.translationX;
|
||||
translateY.value = event.translationY;
|
||||
})
|
||||
.onFinalize(() => {
|
||||
translateX.value = withSpring(0);
|
||||
translateY.value = withSpring(0);
|
||||
}),
|
||||
),
|
||||
[scale, translateX, translateY],
|
||||
);
|
||||
|
||||
return (
|
||||
<GestureDetector gesture={gesture}>
|
||||
<Animated.Image {...props} style={[props.style, animatedStyles]} />
|
||||
</GestureDetector>
|
||||
);
|
||||
};
|
||||
|
||||
export default AnimatedImage;
|
@@ -1,11 +1,13 @@
|
||||
export {
|
||||
MemesList,
|
||||
MemeEditor,
|
||||
MemeFail,
|
||||
MemesHeader,
|
||||
MemeTagSelector,
|
||||
MemeViewItem,
|
||||
} from './memes';
|
||||
export { TagChip, TagEditor, TagPreview, TagRow, TagsHeader } from './tags';
|
||||
export { default as AnimatedImage } from './animatedImage';
|
||||
export { default as FloatingActionButton } from './floatingActionButton';
|
||||
export { default as HideableBottomNavigationBar } from './hideableBottomNavigationBar';
|
||||
export { default as HideableHeader } from './hideableHeader';
|
||||
|
@@ -3,8 +3,7 @@ import { HelperText, Text, TextInput, useTheme } from 'react-native-paper';
|
||||
import { Image } from 'react-native';
|
||||
import { useSafeAreaFrame } from 'react-native-safe-area-context';
|
||||
import { useImageDimensions } from '@react-native-community/hooks/lib/useImageDimensions';
|
||||
import LoadingView from '../loadingView';
|
||||
import { MemeFail, MemeTagSelector } from '.';
|
||||
import { MemeFail, MemeTagSelector, LoadingView } from '..';
|
||||
import { Tag } from '../../database';
|
||||
import { StringValidationResult, validateMemeTitle } from '../../utilities';
|
||||
|
||||
|
@@ -1,14 +1,12 @@
|
||||
import React from 'react';
|
||||
import { ImageZoom } from '@likashefqet/react-native-image-zoom';
|
||||
import { StyleSheet, View } from 'react-native';
|
||||
import { useSafeAreaFrame } from 'react-native-safe-area-context';
|
||||
import { useImageDimensions } from '@react-native-community/hooks';
|
||||
import { AndroidScoped } from 'react-native-file-access';
|
||||
import LoadingView from '../loadingView';
|
||||
import { Meme } from '../../database';
|
||||
import MemeFail from './memeFail';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { Meme } from '../../database';
|
||||
import { RootState } from '../../state';
|
||||
import { AnimatedImage, LoadingView, MemeFail } from '..';
|
||||
|
||||
const memeViewItemStyles = StyleSheet.create({
|
||||
view: {
|
||||
@@ -47,7 +45,7 @@ const MemeViewItem = ({ meme }: { meme: Meme }) => {
|
||||
iconSize={50}
|
||||
/>
|
||||
) : (
|
||||
<ImageZoom
|
||||
<AnimatedImage
|
||||
source={{ uri }}
|
||||
style={
|
||||
dimensions.aspectRatio > width / (height - 128)
|
||||
@@ -61,7 +59,6 @@ const MemeViewItem = ({ meme }: { meme: Meme }) => {
|
||||
height: height - 128,
|
||||
}
|
||||
}
|
||||
minScale={0.5}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
|
Reference in New Issue
Block a user