Fix flicker
Reanimated values and React props were out of sync. Prepare each image's styles separately to avoid that.
This commit is contained in:
@@ -17,7 +17,7 @@ import {
|
|||||||
StyleSheet,
|
StyleSheet,
|
||||||
View,
|
View,
|
||||||
} from 'react-native'
|
} from 'react-native'
|
||||||
import {Gesture} from 'react-native-gesture-handler'
|
import {Gesture, PanGesture} from 'react-native-gesture-handler'
|
||||||
import PagerView from 'react-native-pager-view'
|
import PagerView from 'react-native-pager-view'
|
||||||
import {
|
import {
|
||||||
cancelAnimation,
|
cancelAnimation,
|
||||||
@@ -108,47 +108,6 @@ function ImageViewing({
|
|||||||
return {pointerEvents: 'auto'}
|
return {pointerEvents: 'auto'}
|
||||||
})
|
})
|
||||||
|
|
||||||
const activeInterpolation = useDerivedValue(() => {
|
|
||||||
const image = images[imageIndex]
|
|
||||||
if (image.thumbRect && image.dimensions) {
|
|
||||||
const interpolatedTransform = interpolateTransform(
|
|
||||||
openProgress.value,
|
|
||||||
image.thumbRect,
|
|
||||||
SCREEN,
|
|
||||||
image.dimensions,
|
|
||||||
)
|
|
||||||
return interpolatedTransform
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const activeImageContainerStyle = useAnimatedStyle(() => {
|
|
||||||
if (openProgress.value === 1 || dismissSwipeTranslateY.value !== 0) {
|
|
||||||
return {
|
|
||||||
transform: [{translateY: dismissSwipeTranslateY.value}],
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const interpolation = activeInterpolation.value
|
|
||||||
if (interpolation) {
|
|
||||||
return {
|
|
||||||
transform: interpolation.transform,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
transform: [],
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const activeImageStyle = useAnimatedStyle(() => {
|
|
||||||
const interpolation = activeInterpolation.value
|
|
||||||
if (interpolation) {
|
|
||||||
return {
|
|
||||||
height: interpolation.height,
|
|
||||||
width: interpolation.width,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {}
|
|
||||||
})
|
|
||||||
|
|
||||||
const dismissSwipePan = Gesture.Pan()
|
const dismissSwipePan = Gesture.Pan()
|
||||||
.enabled(!isScaled)
|
.enabled(!isScaled)
|
||||||
.activeOffsetY([-10, 10])
|
.activeOffsetY([-10, 10])
|
||||||
@@ -248,20 +207,21 @@ function ImageViewing({
|
|||||||
overdrag={true}
|
overdrag={true}
|
||||||
style={styles.pager}>
|
style={styles.pager}>
|
||||||
{images.map((imageSrc, i) => (
|
{images.map((imageSrc, i) => (
|
||||||
<Animated.View
|
<LightboxPage
|
||||||
key={imageSrc.uri}
|
key={imageSrc.uri}
|
||||||
style={imageIndex === i ? activeImageContainerStyle : null}>
|
imageSrc={imageSrc}
|
||||||
<ImageItem
|
onRequestClose={onRequestClose}
|
||||||
onTap={onTap}
|
onTap={onTap}
|
||||||
onZoom={onZoom}
|
onZoom={onZoom}
|
||||||
imageSrc={imageSrc}
|
isActive={i === imageIndex}
|
||||||
onRequestClose={onRequestClose}
|
isPagingAndroid={isPagingAndroid}
|
||||||
isPagingAndroid={isPagingAndroid}
|
isFlyingAway={isFlyingAway}
|
||||||
showControls={showControls}
|
isScaled={isScaled}
|
||||||
dismissSwipePan={imageIndex === i ? dismissSwipePan : null}
|
showControls={showControls}
|
||||||
imageStyle={imageIndex === i ? activeImageStyle : null}
|
openProgress={openProgress}
|
||||||
/>
|
dismissSwipePan={dismissSwipePan}
|
||||||
</Animated.View>
|
dismissSwipeTranslateY={dismissSwipeTranslateY}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</PagerView>
|
</PagerView>
|
||||||
<Animated.View style={[styles.footer, animatedFooterStyle]}>
|
<Animated.View style={[styles.footer, animatedFooterStyle]}>
|
||||||
@@ -277,6 +237,87 @@ function ImageViewing({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function LightboxPage({
|
||||||
|
imageSrc,
|
||||||
|
onRequestClose,
|
||||||
|
onTap,
|
||||||
|
onZoom,
|
||||||
|
isActive,
|
||||||
|
isPagingAndroid,
|
||||||
|
showControls,
|
||||||
|
openProgress,
|
||||||
|
dismissSwipeTranslateY,
|
||||||
|
dismissSwipePan,
|
||||||
|
}: {
|
||||||
|
imageSrc: ImageSource
|
||||||
|
onRequestClose: () => void
|
||||||
|
onTap: () => void
|
||||||
|
onZoom: (scaled: boolean) => void
|
||||||
|
isActive: boolean
|
||||||
|
isPagingAndroid: boolean
|
||||||
|
isFlyingAway: SharedValue<boolean>
|
||||||
|
isScaled: boolean
|
||||||
|
showControls: boolean
|
||||||
|
openProgress: SharedValue<number>
|
||||||
|
dismissSwipeTranslateY: SharedValue<number>
|
||||||
|
dismissSwipePan: PanGesture
|
||||||
|
}) {
|
||||||
|
const {thumbRect, dimensions} = imageSrc
|
||||||
|
const imageAspect = dimensions
|
||||||
|
? dimensions.width / dimensions.height
|
||||||
|
: undefined
|
||||||
|
const finalWidth = SCREEN.width
|
||||||
|
const finalHeight = imageAspect ? SCREEN.width / imageAspect : undefined
|
||||||
|
|
||||||
|
const interpolation = useDerivedValue(() => {
|
||||||
|
if (isActive && thumbRect && dimensions && openProgress.value < 1) {
|
||||||
|
return interpolateTransform(
|
||||||
|
openProgress.value,
|
||||||
|
thumbRect,
|
||||||
|
SCREEN,
|
||||||
|
dimensions,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
const translateY = isActive ? dismissSwipeTranslateY.value : 0
|
||||||
|
return {
|
||||||
|
transform: [{translateY}],
|
||||||
|
width: finalWidth,
|
||||||
|
height: finalHeight,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const containerStyle = useAnimatedStyle(() => {
|
||||||
|
const {transform} = interpolation.value
|
||||||
|
return {
|
||||||
|
flex: 1,
|
||||||
|
transform,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const imageStyle = useAnimatedStyle(() => {
|
||||||
|
const {width, height} = interpolation.value
|
||||||
|
return {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Animated.View style={containerStyle}>
|
||||||
|
<ImageItem
|
||||||
|
onTap={onTap}
|
||||||
|
onZoom={onZoom}
|
||||||
|
imageSrc={imageSrc}
|
||||||
|
onRequestClose={onRequestClose}
|
||||||
|
isPagingAndroid={isPagingAndroid}
|
||||||
|
showControls={showControls}
|
||||||
|
dismissSwipePan={isActive ? dismissSwipePan : null}
|
||||||
|
imageStyle={imageStyle}
|
||||||
|
/>
|
||||||
|
</Animated.View>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function LightboxFooter({
|
function LightboxFooter({
|
||||||
images,
|
images,
|
||||||
index,
|
index,
|
||||||
|
|||||||
Reference in New Issue
Block a user