Port remaining lightbox code to Reanimated (#1669)
* Port remaining lightbox code to Reanimated * Fix memoizationzio/stable
parent
0b44af38ea
commit
a48c213af5
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue