Skip to content

Commit 308806e

Browse files
authored
fix: way of reading the value from animated shared values in the components (#2738)
* fix: way of reading the value from animated shared values in the components * fix: unify styles to one hook * fix: lint issues
1 parent 4756d0d commit 308806e

File tree

7 files changed

+266
-135
lines changed

7 files changed

+266
-135
lines changed

package/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,9 @@
8383
"@op-engineering/op-sqlite": ">=6.0.4",
8484
"@react-native-community/netinfo": ">=11.3.1",
8585
"react-native": ">=0.67.0",
86-
"react-native-svg": ">=12.3.0",
8786
"react-native-gesture-handler": ">=2.14.0",
88-
"react-native-reanimated": ">=3.8.0"
87+
"react-native-reanimated": ">=3.8.0",
88+
"react-native-svg": ">=12.3.0"
8989
},
9090
"peerDependenciesMeta": {
9191
"@op-engineering/op-sqlite": {
@@ -144,8 +144,8 @@
144144
"react": "18.2.0",
145145
"react-native": "0.73.6",
146146
"react-native-builder-bob": "0.23.1",
147-
"react-native-gesture-handler": "~2.8.0",
148-
"react-native-reanimated": "3.7.0",
147+
"react-native-gesture-handler": "~2.16.1",
148+
"react-native-reanimated": "~3.10.0",
149149
"react-native-svg": "15.1.0",
150150
"react-test-renderer": "18.2.0",
151151
"typescript": "5.0.4",

package/src/components/ImageGallery/ImageGallery.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,6 @@ export const clamp = (value: number, lowerBound: number, upperBound: number) =>
640640
const styles = StyleSheet.create({
641641
animatedContainer: {
642642
alignItems: 'center',
643-
backgroundColor: 'red',
644643
flexDirection: 'row',
645644
},
646645
});

package/src/components/ImageGallery/components/AnimatedGalleryImage.tsx

Lines changed: 13 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import React from 'react';
22
import { View } from 'react-native';
33
import type { ImageStyle, StyleProp } from 'react-native';
4-
import Animated, { SharedValue, useAnimatedStyle } from 'react-native-reanimated';
4+
import Animated, { SharedValue } from 'react-native-reanimated';
55

6-
import { useViewport } from '../../../hooks/useViewport';
6+
import { useAnimatedGalleryStyle } from '../hooks/useAnimatedGalleryStyle';
77

88
const oneEighth = 1 / 8;
99

@@ -38,43 +38,17 @@ export const AnimatedGalleryImage = React.memo(
3838
translateX,
3939
translateY,
4040
} = props;
41-
const { vw } = useViewport();
4241

43-
const screenWidth = vw(100);
44-
const halfScreenWidth = vw(50);
45-
46-
/**
47-
* The current image, designated by selected is scaled and translated
48-
* based on the gestures. The rendered images before and after the
49-
* currently selected image also translated in X if the scale is
50-
* greater than one so they keep the same distance from the selected
51-
* image as it is scaled. If the scale is less than one they stay in
52-
* place as to not come into the screen when the image shrinks.
53-
*/
54-
const animatedGalleryImageStyle = useAnimatedStyle<ImageStyle>(() => {
55-
const xScaleOffset = -7 * screenWidth * (0.5 + index);
56-
const yScaleOffset = -screenHeight * 3.5;
57-
return {
58-
transform: [
59-
{
60-
translateX: selected
61-
? translateX.value + xScaleOffset
62-
: scale.value < 1 || scale.value !== offsetScale.value
63-
? xScaleOffset
64-
: previous
65-
? translateX.value - halfScreenWidth * (scale.value - 1) + xScaleOffset
66-
: translateX.value + halfScreenWidth * (scale.value - 1) + xScaleOffset,
67-
},
68-
{
69-
translateY: selected ? translateY.value + yScaleOffset : yScaleOffset,
70-
},
71-
{
72-
scale: selected ? scale.value / 8 : oneEighth,
73-
},
74-
{ scaleX: -1 },
75-
],
76-
};
77-
}, [previous, selected]);
42+
const animatedStyles = useAnimatedGalleryStyle({
43+
index,
44+
offsetScale,
45+
previous,
46+
scale,
47+
screenHeight,
48+
selected,
49+
translateX,
50+
translateY,
51+
});
7852

7953
/**
8054
* An empty view is rendered for images not close to the currently
@@ -90,20 +64,7 @@ export const AnimatedGalleryImage = React.memo(
9064
accessibilityLabel={accessibilityLabel}
9165
resizeMode={'contain'}
9266
source={{ uri: photo.uri }}
93-
style={[
94-
animatedGalleryImageStyle,
95-
{
96-
transform: [
97-
{ scaleX: -1 },
98-
{ translateY: -screenHeight * 3.5 },
99-
{
100-
translateX: -translateX.value + 7 * screenWidth * (0.5 + index),
101-
},
102-
{ scale: oneEighth },
103-
],
104-
},
105-
style,
106-
]}
67+
style={[...animatedStyles, style]}
10768
/>
10869
);
10970
},

package/src/components/ImageGallery/components/AnimatedGalleryVideo.tsx

Lines changed: 13 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import React, { useState } from 'react';
22
import { StyleSheet, View, ViewStyle } from 'react-native';
33
import type { StyleProp } from 'react-native';
4-
import Animated, { SharedValue, useAnimatedStyle } from 'react-native-reanimated';
4+
import Animated, { SharedValue } from 'react-native-reanimated';
55

6-
import { useViewport } from '../../../hooks/useViewport';
76
import {
87
isVideoPlayerAvailable,
98
PlaybackStatus,
@@ -14,6 +13,7 @@ import {
1413
} from '../../../native';
1514

1615
import { Spinner } from '../../UIComponents/Spinner';
16+
import { useAnimatedGalleryStyle } from '../hooks/useAnimatedGalleryStyle';
1717

1818
const oneEighth = 1 / 8;
1919

@@ -72,11 +72,6 @@ export const AnimatedGalleryVideo = React.memo(
7272
translateY,
7373
videoRef,
7474
} = props;
75-
const { vw } = useViewport();
76-
77-
const screenWidth = vw(100);
78-
const halfScreenWidth = vw(50);
79-
8075
const onLoadStart = () => {
8176
setOpacity(1);
8277
};
@@ -131,30 +126,16 @@ export const AnimatedGalleryVideo = React.memo(
131126
}
132127
};
133128

134-
const animatedViewStyles = useAnimatedStyle<ViewStyle>(() => {
135-
const xScaleOffset = -7 * screenWidth * (0.5 + index);
136-
const yScaleOffset = -screenHeight * 3.5;
137-
return {
138-
transform: [
139-
{
140-
translateX: selected
141-
? translateX.value + xScaleOffset
142-
: scale.value < 1 || scale.value !== offsetScale.value
143-
? xScaleOffset
144-
: previous
145-
? translateX.value - halfScreenWidth * (scale.value - 1) + xScaleOffset
146-
: translateX.value + halfScreenWidth * (scale.value - 1) + xScaleOffset,
147-
},
148-
{
149-
translateY: selected ? translateY.value + yScaleOffset : yScaleOffset,
150-
},
151-
{
152-
scale: selected ? scale.value / 8 : oneEighth,
153-
},
154-
{ scaleX: -1 },
155-
],
156-
};
157-
}, [previous, selected]);
129+
const animatedStyles = useAnimatedGalleryStyle({
130+
index,
131+
offsetScale,
132+
previous,
133+
scale,
134+
screenHeight,
135+
selected,
136+
translateX,
137+
translateY,
138+
});
158139

159140
/**
160141
* An empty view is rendered for images not close to the currently
@@ -171,23 +152,7 @@ export const AnimatedGalleryVideo = React.memo(
171152
}
172153

173154
return (
174-
<Animated.View
175-
accessibilityLabel='Image Gallery Video'
176-
style={[
177-
animatedViewStyles,
178-
{
179-
transform: [
180-
{ scaleX: -1 },
181-
{ translateY: -screenHeight * 3.5 },
182-
{
183-
translateX: -translateX.value + 7 * screenWidth * (0.5 + index),
184-
},
185-
{ scale: oneEighth },
186-
],
187-
},
188-
style,
189-
]}
190-
>
155+
<Animated.View accessibilityLabel='Image Gallery Video' style={[...animatedStyles, style]}>
191156
{isVideoPlayerAvailable() ? (
192157
<Video
193158
onBuffer={onBuffer}
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import type { ImageStyle } from 'react-native';
2+
import { SharedValue, useAnimatedStyle } from 'react-native-reanimated';
3+
4+
import { useViewport } from '../../../hooks/useViewport';
5+
6+
type Props = {
7+
index: number;
8+
offsetScale: SharedValue<number>;
9+
previous: boolean;
10+
scale: SharedValue<number>;
11+
screenHeight: number;
12+
selected: boolean;
13+
translateX: SharedValue<number>;
14+
translateY: SharedValue<number>;
15+
};
16+
17+
const oneEighth = 1 / 8;
18+
19+
export const useAnimatedGalleryStyle = ({
20+
index,
21+
offsetScale,
22+
previous,
23+
scale,
24+
screenHeight,
25+
selected,
26+
translateX,
27+
translateY,
28+
}: Props) => {
29+
const { vw } = useViewport();
30+
31+
const screenWidth = vw(100);
32+
const halfScreenWidth = vw(50);
33+
34+
/**
35+
* The current image, designated by selected is scaled and translated
36+
* based on the gestures. The rendered images before and after the
37+
* currently selected image also translated in X if the scale is
38+
* greater than one so they keep the same distance from the selected
39+
* image as it is scaled. If the scale is less than one they stay in
40+
* place as to not come into the screen when the image shrinks.
41+
*/
42+
const animatedGalleryStyle = useAnimatedStyle<ImageStyle>(() => {
43+
const xScaleOffset = -7 * screenWidth * (0.5 + index);
44+
const yScaleOffset = -screenHeight * 3.5;
45+
return {
46+
transform: [
47+
{
48+
translateX: selected
49+
? translateX.value + xScaleOffset
50+
: scale.value < 1 || scale.value !== offsetScale.value
51+
? xScaleOffset
52+
: previous
53+
? translateX.value - halfScreenWidth * (scale.value - 1) + xScaleOffset
54+
: translateX.value + halfScreenWidth * (scale.value - 1) + xScaleOffset,
55+
},
56+
{
57+
translateY: selected ? translateY.value + yScaleOffset : yScaleOffset,
58+
},
59+
{
60+
scale: selected ? scale.value / 8 : oneEighth,
61+
},
62+
{ scaleX: -1 },
63+
],
64+
};
65+
}, [previous, selected]);
66+
67+
const animatedStyles = useAnimatedStyle(() => {
68+
const xScaleOffset = -7 * screenWidth * (0.5 + index);
69+
const yScaleOffset = -screenHeight * 3.5;
70+
return {
71+
transform: [
72+
{ scaleX: -1 },
73+
{ translateY: yScaleOffset },
74+
{
75+
translateX: -translateX.value - xScaleOffset,
76+
},
77+
{ scale: oneEighth },
78+
],
79+
};
80+
}, []);
81+
82+
return [animatedGalleryStyle, animatedStyles];
83+
};

0 commit comments

Comments
 (0)