Fix animations and gestures getting reset on state updates in the lightbox (#1618)
* Fix translation resetting on state update * Copy getImageStyles into iOS and Android forks * Fix opacity resetting on state updatezio/stable
parent
260b03a05c
commit
4ec5fabdd1
|
@ -22,7 +22,7 @@ import {Image} from 'expo-image'
|
|||
import useImageDimensions from '../../hooks/useImageDimensions'
|
||||
import usePanResponder from '../../hooks/usePanResponder'
|
||||
|
||||
import {getImageStyles, getImageTransform} from '../../utils'
|
||||
import {getImageTransform} from '../../utils'
|
||||
import {ImageSource} from '../../@types'
|
||||
import {ImageLoading} from './ImageLoading'
|
||||
|
||||
|
@ -133,4 +133,27 @@ const styles = StyleSheet.create({
|
|||
},
|
||||
})
|
||||
|
||||
const getImageStyles = (
|
||||
image: {width: number; height: number} | null,
|
||||
translate: Animated.ValueXY,
|
||||
scale?: Animated.Value,
|
||||
) => {
|
||||
if (!image?.width || !image?.height) {
|
||||
return {width: 0, height: 0}
|
||||
}
|
||||
|
||||
const transform = translate.getTranslateTransform()
|
||||
|
||||
if (scale) {
|
||||
// @ts-ignore TODO - is scale incorrect? might need to remove -prf
|
||||
transform.push({scale}, {perspective: new Animated.Value(1000)})
|
||||
}
|
||||
|
||||
return {
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
transform,
|
||||
}
|
||||
}
|
||||
|
||||
export default React.memo(ImageItem)
|
||||
|
|
|
@ -23,7 +23,7 @@ import {Image} from 'expo-image'
|
|||
|
||||
import useImageDimensions from '../../hooks/useImageDimensions'
|
||||
|
||||
import {getImageStyles, getImageTransform} from '../../utils'
|
||||
import {getImageTransform} from '../../utils'
|
||||
import {ImageSource} from '../../@types'
|
||||
import {ImageLoading} from './ImageLoading'
|
||||
|
||||
|
@ -52,23 +52,14 @@ const ImageItem = ({imageSrc, onZoom, onRequestClose}: Props) => {
|
|||
const [scaled, setScaled] = useState(false)
|
||||
const imageDimensions = useImageDimensions(imageSrc)
|
||||
const [translate, scale] = getImageTransform(imageDimensions, SCREEN)
|
||||
|
||||
// TODO: It's not valid to reinitialize Animated values during render.
|
||||
// This is a bug.
|
||||
const scrollValueY = new Animated.Value(0)
|
||||
const scaleValue = new Animated.Value(scale || 1)
|
||||
const translateValue = new Animated.ValueXY(translate)
|
||||
const [scrollValueY] = useState(() => new Animated.Value(0))
|
||||
const maxScrollViewZoom = MAX_SCALE / (scale || 1)
|
||||
|
||||
const imageOpacity = scrollValueY.interpolate({
|
||||
inputRange: [-SWIPE_CLOSE_OFFSET, 0, SWIPE_CLOSE_OFFSET],
|
||||
outputRange: [0.5, 1, 0.5],
|
||||
})
|
||||
const imagesStyles = getImageStyles(
|
||||
imageDimensions,
|
||||
translateValue,
|
||||
scaleValue,
|
||||
)
|
||||
const imagesStyles = getImageStyles(imageDimensions, translate, scale || 1)
|
||||
const imageStylesWithOpacity = {...imagesStyles, opacity: imageOpacity}
|
||||
|
||||
const onScrollEndDrag = useCallback(
|
||||
|
@ -260,4 +251,28 @@ const getZoomRectAfterDoubleTap = (
|
|||
}
|
||||
}
|
||||
|
||||
const getImageStyles = (
|
||||
image: {width: number; height: number} | null,
|
||||
translate: {readonly x: number; readonly y: number} | undefined,
|
||||
scale?: number,
|
||||
) => {
|
||||
if (!image?.width || !image?.height) {
|
||||
return {width: 0, height: 0}
|
||||
}
|
||||
const transform = []
|
||||
if (translate) {
|
||||
transform.push({translateX: translate.x})
|
||||
transform.push({translateY: translate.y})
|
||||
}
|
||||
if (scale) {
|
||||
// @ts-ignore TODO - is scale incorrect? might need to remove -prf
|
||||
transform.push({scale}, {perspective: new Animated.Value(1000)})
|
||||
}
|
||||
return {
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
transform,
|
||||
}
|
||||
}
|
||||
|
||||
export default React.memo(ImageItem)
|
||||
|
|
|
@ -69,11 +69,12 @@ function ImageViewing({
|
|||
const imageList = useRef<VirtualizedList<ImageSource>>(null)
|
||||
const [opacity, setOpacity] = useState(1)
|
||||
const [currentImageIndex, setImageIndex] = useState(imageIndex)
|
||||
|
||||
// TODO: It's not valid to reinitialize Animated values during render.
|
||||
// This is a bug.
|
||||
const headerTranslate = new Animated.ValueXY(INITIAL_POSITION)
|
||||
const footerTranslate = new Animated.ValueXY(INITIAL_POSITION)
|
||||
const [headerTranslate] = useState(
|
||||
() => new Animated.ValueXY(INITIAL_POSITION),
|
||||
)
|
||||
const [footerTranslate] = useState(
|
||||
() => new Animated.ValueXY(INITIAL_POSITION),
|
||||
)
|
||||
|
||||
const toggleBarsVisible = (isVisible: boolean) => {
|
||||
if (isVisible) {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*
|
||||
*/
|
||||
|
||||
import {Animated} from 'react-native'
|
||||
import {Dimensions, Position} from './@types'
|
||||
|
||||
export const getImageTransform = (
|
||||
|
@ -25,29 +24,6 @@ export const getImageTransform = (
|
|||
return [{x, y}, scale] as const
|
||||
}
|
||||
|
||||
export const getImageStyles = (
|
||||
image: Dimensions | null,
|
||||
translate: Animated.ValueXY,
|
||||
scale?: Animated.Value,
|
||||
) => {
|
||||
if (!image?.width || !image?.height) {
|
||||
return {width: 0, height: 0}
|
||||
}
|
||||
|
||||
const transform = translate.getTranslateTransform()
|
||||
|
||||
if (scale) {
|
||||
// @ts-ignore TODO - is scale incorrect? might need to remove -prf
|
||||
transform.push({scale}, {perspective: new Animated.Value(1000)})
|
||||
}
|
||||
|
||||
return {
|
||||
width: image.width,
|
||||
height: image.height,
|
||||
transform,
|
||||
}
|
||||
}
|
||||
|
||||
export const getImageTranslate = (
|
||||
image: Dimensions,
|
||||
screen: Dimensions,
|
||||
|
|
Loading…
Reference in New Issue