Fix gallery view

This commit is contained in:
Dan Abramov
2023-09-29 16:58:46 +01:00
parent 44733bb390
commit ad3644e668
2 changed files with 67 additions and 10 deletions
@@ -10,7 +10,9 @@ import {
} from 'react-native' } from 'react-native'
import {Image} from 'expo-image' import {Image} from 'expo-image'
import Animated, { import Animated, {
runOnJS,
useAnimatedStyle, useAnimatedStyle,
useAnimatedReaction,
useDerivedValue, useDerivedValue,
useSharedValue, useSharedValue,
} from 'react-native-reanimated' } from 'react-native-reanimated'
@@ -38,7 +40,7 @@ type Props = {
doubleTapToZoomEnabled?: boolean doubleTapToZoomEnabled?: boolean
} }
type Matrix3 = readonly [ type Matrix3 = [
number, number,
number, number,
number, number,
@@ -106,6 +108,14 @@ function prependPinch(t, scale, origin, translation) {
prependTranslate(t, -origin.x, -origin.y); prependTranslate(t, -origin.x, -origin.y);
} }
function applyRounding(t) {
'worklet'
t[2] = Math.round(t[2])
t[5] = Math.round(t[5])
t[0] = Math.round(t[0] * 200) / 200;
t[4] = Math.round(t[0] * 200) / 200;
}
function toStyle(t) { function toStyle(t) {
"worklet"; "worklet";
const [translateX, translateY, scale] = readTransform(t) const [translateX, translateY, scale] = readTransform(t)
@@ -154,6 +164,7 @@ const ImageItem = ({
swipeToCloseEnabled = true, swipeToCloseEnabled = true,
doubleTapToZoomEnabled = true, doubleTapToZoomEnabled = true,
}: Props) => { }: Props) => {
const [isScaled, setIsScaled] = useState(false)
const imageDimensions = useImageDimensions(imageSrc) const imageDimensions = useImageDimensions(imageSrc)
const committedTransform = useSharedValue(initialTransform) const committedTransform = useSharedValue(initialTransform)
const pinchOrigin = useSharedValue({ x: 0, y: 0 }) const pinchOrigin = useSharedValue({ x: 0, y: 0 })
@@ -161,6 +172,24 @@ const ImageItem = ({
const pinchTranslation = useSharedValue({ x: 0, y: 0 }) const pinchTranslation = useSharedValue({ x: 0, y: 0 })
const panTranslation = useSharedValue({ x: 0, y: 0 }) const panTranslation = useSharedValue({ x: 0, y: 0 })
useAnimatedReaction(
() => {
if (pinchScale.value !== 1) {
return true;
}
const [,,scale] = readTransform(committedTransform.value)
if (scale !== 1) {
return true;
}
return false;
},
(isScaledNow, wasScaledBefore) => {
if (isScaledNow !== wasScaledBefore) {
runOnJS(setIsScaled)(isScaledNow)
}
}
)
const animatedStyle = useAnimatedStyle(() => { const animatedStyle = useAnimatedStyle(() => {
let t = createTransform(); let t = createTransform();
prependPan(t, panTranslation.value); prependPan(t, panTranslation.value);
@@ -210,6 +239,7 @@ const ImageItem = ({
let t = createTransform(); let t = createTransform();
prependPinch(t, pinchScale.value, pinchOrigin.value, pinchTranslation.value) prependPinch(t, pinchScale.value, pinchOrigin.value, pinchTranslation.value)
prependTransform(t, committedTransform.value); prependTransform(t, committedTransform.value);
applyRounding(t)
committedTransform.value = t committedTransform.value = t
pinchScale.value = 1; pinchScale.value = 1;
pinchOrigin.value = { x: 0, y: 0 }; pinchOrigin.value = { x: 0, y: 0 };
@@ -218,6 +248,7 @@ const ImageItem = ({
const pan = Gesture.Pan() const pan = Gesture.Pan()
.averageTouches(true) .averageTouches(true)
.enabled(isScaled)
.onChange((e) => { .onChange((e) => {
if (!imageDimensions) { if (!imageDimensions) {
return; return;
@@ -232,6 +263,7 @@ const ImageItem = ({
let t = createTransform(); let t = createTransform();
prependPan(t, panTranslation.value) prependPan(t, panTranslation.value)
prependTransform(t, committedTransform.value); prependTransform(t, committedTransform.value);
applyRounding(t)
committedTransform.value = t committedTransform.value = t
panTranslation.value = { x: 0, y: 0 }; panTranslation.value = { x: 0, y: 0 };
}); });
+34 -9
View File
@@ -129,15 +129,40 @@ function ImageViewing({
<ImageDefaultHeader onRequestClose={onRequestCloseEnhanced} /> <ImageDefaultHeader onRequestClose={onRequestCloseEnhanced} />
)} )}
</Animated.View> </Animated.View>
{/* TODO: show gallery again */} <VirtualizedList
<ImageItem ref={imageList}
onZoom={onZoom} data={images}
imageSrc={images[0]} horizontal
onRequestClose={onRequestCloseEnhanced} pagingEnabled
onLongPress={onLongPress} showsHorizontalScrollIndicator={false}
delayLongPress={delayLongPress} showsVerticalScrollIndicator={false}
swipeToCloseEnabled={swipeToCloseEnabled} getItem={(_, index) => images[index]}
doubleTapToZoomEnabled={doubleTapToZoomEnabled} getItemCount={() => images.length}
getItemLayout={(_, index) => ({
length: SCREEN_WIDTH,
offset: SCREEN_WIDTH * index,
index,
})}
renderItem={({item: imageSrc}) => (
<ImageItem
onZoom={onZoom}
imageSrc={imageSrc}
onRequestClose={onRequestCloseEnhanced}
onLongPress={onLongPress}
delayLongPress={delayLongPress}
swipeToCloseEnabled={swipeToCloseEnabled}
doubleTapToZoomEnabled={doubleTapToZoomEnabled}
/>
)}
onMomentumScrollEnd={onScroll}
//@ts-ignore
keyExtractor={(imageSrc, index) =>
keyExtractor
? keyExtractor(imageSrc, index)
: typeof imageSrc === 'number'
? `${imageSrc}`
: imageSrc.uri
}
/> />
{typeof FooterComponent !== 'undefined' && ( {typeof FooterComponent !== 'undefined' && (
<Animated.View style={[styles.footer, {transform: footerTransform}]}> <Animated.View style={[styles.footer, {transform: footerTransform}]}>