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 useImageDimensions from '../../hooks/useImageDimensions'
|
||||||
import usePanResponder from '../../hooks/usePanResponder'
|
import usePanResponder from '../../hooks/usePanResponder'
|
||||||
|
|
||||||
import {getImageStyles, getImageTransform} from '../../utils'
|
import {getImageTransform} from '../../utils'
|
||||||
import {ImageSource} from '../../@types'
|
import {ImageSource} from '../../@types'
|
||||||
import {ImageLoading} from './ImageLoading'
|
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)
|
export default React.memo(ImageItem)
|
||||||
|
|
|
@ -23,7 +23,7 @@ import {Image} from 'expo-image'
|
||||||
|
|
||||||
import useImageDimensions from '../../hooks/useImageDimensions'
|
import useImageDimensions from '../../hooks/useImageDimensions'
|
||||||
|
|
||||||
import {getImageStyles, getImageTransform} from '../../utils'
|
import {getImageTransform} from '../../utils'
|
||||||
import {ImageSource} from '../../@types'
|
import {ImageSource} from '../../@types'
|
||||||
import {ImageLoading} from './ImageLoading'
|
import {ImageLoading} from './ImageLoading'
|
||||||
|
|
||||||
|
@ -52,23 +52,14 @@ const ImageItem = ({imageSrc, onZoom, onRequestClose}: Props) => {
|
||||||
const [scaled, setScaled] = useState(false)
|
const [scaled, setScaled] = useState(false)
|
||||||
const imageDimensions = useImageDimensions(imageSrc)
|
const imageDimensions = useImageDimensions(imageSrc)
|
||||||
const [translate, scale] = getImageTransform(imageDimensions, SCREEN)
|
const [translate, scale] = getImageTransform(imageDimensions, SCREEN)
|
||||||
|
const [scrollValueY] = useState(() => new Animated.Value(0))
|
||||||
// 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 maxScrollViewZoom = MAX_SCALE / (scale || 1)
|
const maxScrollViewZoom = MAX_SCALE / (scale || 1)
|
||||||
|
|
||||||
const imageOpacity = scrollValueY.interpolate({
|
const imageOpacity = scrollValueY.interpolate({
|
||||||
inputRange: [-SWIPE_CLOSE_OFFSET, 0, SWIPE_CLOSE_OFFSET],
|
inputRange: [-SWIPE_CLOSE_OFFSET, 0, SWIPE_CLOSE_OFFSET],
|
||||||
outputRange: [0.5, 1, 0.5],
|
outputRange: [0.5, 1, 0.5],
|
||||||
})
|
})
|
||||||
const imagesStyles = getImageStyles(
|
const imagesStyles = getImageStyles(imageDimensions, translate, scale || 1)
|
||||||
imageDimensions,
|
|
||||||
translateValue,
|
|
||||||
scaleValue,
|
|
||||||
)
|
|
||||||
const imageStylesWithOpacity = {...imagesStyles, opacity: imageOpacity}
|
const imageStylesWithOpacity = {...imagesStyles, opacity: imageOpacity}
|
||||||
|
|
||||||
const onScrollEndDrag = useCallback(
|
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)
|
export default React.memo(ImageItem)
|
||||||
|
|
|
@ -69,11 +69,12 @@ function ImageViewing({
|
||||||
const imageList = useRef<VirtualizedList<ImageSource>>(null)
|
const imageList = useRef<VirtualizedList<ImageSource>>(null)
|
||||||
const [opacity, setOpacity] = useState(1)
|
const [opacity, setOpacity] = useState(1)
|
||||||
const [currentImageIndex, setImageIndex] = useState(imageIndex)
|
const [currentImageIndex, setImageIndex] = useState(imageIndex)
|
||||||
|
const [headerTranslate] = useState(
|
||||||
// TODO: It's not valid to reinitialize Animated values during render.
|
() => new Animated.ValueXY(INITIAL_POSITION),
|
||||||
// This is a bug.
|
)
|
||||||
const headerTranslate = new Animated.ValueXY(INITIAL_POSITION)
|
const [footerTranslate] = useState(
|
||||||
const footerTranslate = new Animated.ValueXY(INITIAL_POSITION)
|
() => new Animated.ValueXY(INITIAL_POSITION),
|
||||||
|
)
|
||||||
|
|
||||||
const toggleBarsVisible = (isVisible: boolean) => {
|
const toggleBarsVisible = (isVisible: boolean) => {
|
||||||
if (isVisible) {
|
if (isVisible) {
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {Animated} from 'react-native'
|
|
||||||
import {Dimensions, Position} from './@types'
|
import {Dimensions, Position} from './@types'
|
||||||
|
|
||||||
export const getImageTransform = (
|
export const getImageTransform = (
|
||||||
|
@ -25,29 +24,6 @@ export const getImageTransform = (
|
||||||
return [{x, y}, scale] as const
|
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 = (
|
export const getImageTranslate = (
|
||||||
image: Dimensions,
|
image: Dimensions,
|
||||||
screen: Dimensions,
|
screen: Dimensions,
|
||||||
|
|
Loading…
Reference in New Issue