Port remaining lightbox code to Reanimated (#1669)

* Port remaining lightbox code to Reanimated

* Fix  memoization
zio/stable
dan 2023-10-10 23:48:31 +01:00 committed by GitHub
parent 0b44af38ea
commit a48c213af5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 27 additions and 42 deletions

View File

@ -8,13 +8,14 @@
// Original code copied and simplified from the link below as the codebase is currently not maintained: // Original code copied and simplified from the link below as the codebase is currently not maintained:
// https://github.com/jobtoday/react-native-image-viewing // https://github.com/jobtoday/react-native-image-viewing
import React, {ComponentType, useMemo, useState} from 'react' import React, {ComponentType, useCallback, useMemo, useState} from 'react'
import {Animated, StyleSheet, View, ModalProps, Platform} from 'react-native' import {StyleSheet, View, Platform} from 'react-native'
import ImageItem from './components/ImageItem/ImageItem' import ImageItem from './components/ImageItem/ImageItem'
import ImageDefaultHeader from './components/ImageDefaultHeader' import ImageDefaultHeader from './components/ImageDefaultHeader'
import {ImageSource} from './@types' import {ImageSource} from './@types'
import Animated, {useAnimatedStyle, withSpring} from 'react-native-reanimated'
import {Edge, SafeAreaView} from 'react-native-safe-area-context' import {Edge, SafeAreaView} from 'react-native-safe-area-context'
import PagerView from 'react-native-pager-view' import PagerView from 'react-native-pager-view'
@ -23,19 +24,12 @@ type Props = {
initialImageIndex: number initialImageIndex: number
visible: boolean visible: boolean
onRequestClose: () => void onRequestClose: () => void
presentationStyle?: ModalProps['presentationStyle']
animationType?: ModalProps['animationType']
backgroundColor?: string backgroundColor?: string
HeaderComponent?: ComponentType<{imageIndex: number}> HeaderComponent?: ComponentType<{imageIndex: number}>
FooterComponent?: ComponentType<{imageIndex: number}> FooterComponent?: ComponentType<{imageIndex: number}>
} }
const DEFAULT_BG_COLOR = '#000' const DEFAULT_BG_COLOR = '#000'
const INITIAL_POSITION = {x: 0, y: 0}
const ANIMATION_CONFIG = {
duration: 200,
useNativeDriver: true,
}
function ImageViewing({ function ImageViewing({
images, images,
@ -49,37 +43,25 @@ function ImageViewing({
const [isScaled, setIsScaled] = useState(false) const [isScaled, setIsScaled] = useState(false)
const [isDragging, setIsDragging] = useState(false) const [isDragging, setIsDragging] = useState(false)
const [imageIndex, setImageIndex] = useState(initialImageIndex) const [imageIndex, setImageIndex] = useState(initialImageIndex)
const [headerTranslate] = useState(
() => new Animated.ValueXY(INITIAL_POSITION),
)
const [footerTranslate] = useState(
() => new Animated.ValueXY(INITIAL_POSITION),
)
const toggleBarsVisible = (isVisible: boolean) => { const animatedHeaderStyle = useAnimatedStyle(() => ({
if (isVisible) { transform: [
Animated.parallel([ {
Animated.timing(headerTranslate.y, {...ANIMATION_CONFIG, toValue: 0}), translateY: withClampedSpring(isScaled ? -300 : 0),
Animated.timing(footerTranslate.y, {...ANIMATION_CONFIG, toValue: 0}), },
]).start() ],
} else { }))
Animated.parallel([ const animatedFooterStyle = useAnimatedStyle(() => ({
Animated.timing(headerTranslate.y, { transform: [
...ANIMATION_CONFIG, {
toValue: -300, translateY: withClampedSpring(isScaled ? 300 : 0),
}), },
Animated.timing(footerTranslate.y, { ],
...ANIMATION_CONFIG, }))
toValue: 300,
}),
]).start()
}
}
const onZoom = (nextIsScaled: boolean) => { const onZoom = useCallback((nextIsScaled: boolean) => {
toggleBarsVisible(!nextIsScaled) setIsScaled(nextIsScaled)
setIsScaled(false) }, [])
}
const edges = useMemo(() => { const edges = useMemo(() => {
if (Platform.OS === 'android') { if (Platform.OS === 'android') {
@ -92,8 +74,6 @@ function ImageViewing({
return null return null
} }
const headerTransform = headerTranslate.getTranslateTransform()
const footerTransform = footerTranslate.getTranslateTransform()
return ( return (
<SafeAreaView <SafeAreaView
style={styles.screen} style={styles.screen}
@ -101,7 +81,7 @@ function ImageViewing({
aria-modal aria-modal
accessibilityViewIsModal> accessibilityViewIsModal>
<View style={[styles.container, {backgroundColor}]}> <View style={[styles.container, {backgroundColor}]}>
<Animated.View style={[styles.header, {transform: headerTransform}]}> <Animated.View style={[styles.header, animatedHeaderStyle]}>
{typeof HeaderComponent !== 'undefined' ? ( {typeof HeaderComponent !== 'undefined' ? (
React.createElement(HeaderComponent, { React.createElement(HeaderComponent, {
imageIndex, imageIndex,
@ -134,7 +114,7 @@ function ImageViewing({
))} ))}
</PagerView> </PagerView>
{typeof FooterComponent !== 'undefined' && ( {typeof FooterComponent !== 'undefined' && (
<Animated.View style={[styles.footer, {transform: footerTransform}]}> <Animated.View style={[styles.footer, animatedFooterStyle]}>
{React.createElement(FooterComponent, { {React.createElement(FooterComponent, {
imageIndex, imageIndex,
})} })}
@ -179,4 +159,9 @@ const EnhancedImageViewing = (props: Props) => (
<ImageViewing key={props.initialImageIndex} {...props} /> <ImageViewing key={props.initialImageIndex} {...props} />
) )
function withClampedSpring(value: any) {
'worklet'
return withSpring(value, {overshootClamping: true})
}
export default EnhancedImageViewing export default EnhancedImageViewing