Animate opening

This commit is contained in:
Dan Abramov
2024-10-31 00:34:19 +00:00
parent 0be8c55780
commit d35fcca01e
+47 -7
View File
@@ -57,24 +57,29 @@ const SCREEN_HEIGHT = Dimensions.get('window').height
function ImageViewing({ function ImageViewing({
images, images,
thumbDims: _thumbDims, // TODO: Pass down and use for animation. thumbDims,
initialImageIndex, initialImageIndex,
visible, visible,
onRequestClose, onRequestClose,
onPressSave, onPressSave,
onPressShare, onPressShare,
}: Props) { }: Props) {
const openProgress = useSharedValue(0)
React.useEffect(() => {
openProgress.value = withClampedSpring(1)
}, [openProgress])
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 [showControls, setShowControls] = useState(true) const [showControls, setShowControls] = useState(true)
const dismissSwipeTranslateY = useSharedValue(0) const dismissSwipeTranslateY = useSharedValue(0)
const animatedHeaderStyle = useAnimatedStyle(() => { const animatedHeaderStyle = useAnimatedStyle(() => {
const show = showControls && dismissSwipeTranslateY.value === 0 const show = showControls && dismissSwipeTranslateY.value === 0
return { return {
pointerEvents: show ? 'auto' : 'none', pointerEvents: show ? 'auto' : 'none',
opacity: withClampedSpring(show ? 1 : 0), opacity: withClampedSpring(show && openProgress.value > 0 ? 1 : 0),
transform: [ transform: [
{ {
translateY: withClampedSpring(show ? 0 : -30), translateY: withClampedSpring(show ? 0 : -30),
@@ -86,7 +91,7 @@ function ImageViewing({
const show = showControls && dismissSwipeTranslateY.value === 0 const show = showControls && dismissSwipeTranslateY.value === 0
return { return {
pointerEvents: show ? 'auto' : 'none', pointerEvents: show ? 'auto' : 'none',
opacity: withClampedSpring(show ? 1 : 0), opacity: withClampedSpring(show && openProgress.value > 0 ? 1 : 0),
transform: [ transform: [
{ {
translateY: withClampedSpring(show ? 0 : 30), translateY: withClampedSpring(show ? 0 : 30),
@@ -95,6 +100,9 @@ function ImageViewing({
} }
}) })
// TODO: Apply transform
// const initialTransform = calculateOverlayTransform(SCREEN, thumbDims)
const dismissSwipePan = Gesture.Pan() const dismissSwipePan = Gesture.Pan()
.enabled(!isScaled) .enabled(!isScaled)
.activeOffsetY([-10, 10]) .activeOffsetY([-10, 10])
@@ -137,13 +145,18 @@ function ImageViewing({
}, []) }, [])
const backdropStyle = useAnimatedStyle(() => { const backdropStyle = useAnimatedStyle(() => {
const dismissProgress = Math.min( let opacity
if (openProgress.value < 1) {
opacity = openProgress.value
} else {
opacity =
1 -
Math.min(
Math.abs(dismissSwipeTranslateY.value) / (SCREEN.height / 2), Math.abs(dismissSwipeTranslateY.value) / (SCREEN.height / 2),
1, 1,
) )
return {
opacity: 1 - dismissProgress,
} }
return {opacity}
}) })
const activeImageStyle = useAnimatedStyle(() => { const activeImageStyle = useAnimatedStyle(() => {
return { return {
@@ -290,6 +303,33 @@ function LightboxFooter({
) )
} }
function calculateOverlayTransform(
screenSize: {width: number; height: number},
thumbnailPlacement:
| {
pageX: number
width: number
pageY: number
height: number
}
| null
| undefined,
) {
if (!thumbnailPlacement) {
return null
}
const scale = thumbnailPlacement.width / screenSize.width
const screenCenterX = screenSize.width / 2
const screenCenterY = screenSize.height / 2
const thumbnailCenterX =
thumbnailPlacement.pageX + thumbnailPlacement.width / 2
const thumbnailCenterY =
thumbnailPlacement.pageY + thumbnailPlacement.height / 2
const translateX = (thumbnailCenterX - screenCenterX) / scale
const translateY = (thumbnailCenterY - screenCenterY) / scale
return {scale, translateX, translateY}
}
const styles = StyleSheet.create({ const styles = StyleSheet.create({
screen: { screen: {
position: 'absolute', position: 'absolute',