Skip to content

Commit 76e0968

Browse files
committed
fix: accept interpolated and derived values for from
1 parent 4ac3ec1 commit 76e0968

File tree

4 files changed

+101
-14
lines changed

4 files changed

+101
-14
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,15 @@ A component that converts between an [`Animated.Value`][animated.value] and a [`
2525

2626
It accepts the following props:
2727

28-
- `from`
29-
- `to`
28+
- `from`: Value to read and observe changes from.
3029

31-
The `from` and `to` props need to be a pair of [`Animated.Value`][animated.value] and [`SharedValue`][reanimated.sharedvalue] or vice versa. The value passed to `from` will be used to update the value passed to `to`.
30+
`Animated.Node` - `Animated.Value` and result of modifications such as interpolation (`Animated.AnimatedInterpolation`), addition (`Animated.AnimatedAddition`), etc.
31+
32+
`SharedValue<number>` or `DerivedValue<number>`
33+
34+
- `to`: Value to update when the `from` value changes.
35+
36+
`Animated.Value` or `SharedValue<number>`
3237

3338
Usage:
3439

example/ios/Podfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
PODS:
2-
- AnimatedObserver (0.1.0):
2+
- AnimatedObserver (0.2.0):
33
- boost
44
- DoubleConversion
55
- fast_float
@@ -2789,7 +2789,7 @@ EXTERNAL SOURCES:
27892789
:path: "../node_modules/react-native/ReactCommon/yoga"
27902790

27912791
SPEC CHECKSUMS:
2792-
AnimatedObserver: cce34fdba81fb2efd6cc290484a7214a97dbe8db
2792+
AnimatedObserver: 6303ec1cf6156d60d8b5865b8ac3e6aa3918b132
27932793
boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90
27942794
DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb
27952795
fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6

example/src/Examples.tsx

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import {
1111
AnimatedObserver,
1212
} from 'react-native-animated-observer';
1313
import Reanimated, {
14+
interpolate,
1415
useAnimatedRef,
1516
useAnimatedStyle,
17+
useDerivedValue,
1618
useScrollOffset,
1719
useSharedValue,
1820
type SharedValue,
@@ -21,19 +23,33 @@ import Reanimated, {
2123
export function AnimatedToReanimated() {
2224
const { width } = useWindowDimensions();
2325

26+
const scrollWidth = useScrollWidth();
27+
2428
const positionAnimated = useState(() => new Animated.Value(0))[0];
2529
const positionReanimated = useSharedValue(0);
2630

31+
const positionAnimatedInterpolated = positionAnimated.interpolate({
32+
inputRange: [0, scrollWidth - width],
33+
outputRange: [1, 0],
34+
});
35+
36+
const positionReanimatedInterpolated = useSharedValue(scrollWidth);
37+
2738
return (
2839
<View style={styles.container}>
2940
<AnimatedConverter from={positionAnimated} to={positionReanimated} />
41+
<AnimatedConverter
42+
from={positionAnimatedInterpolated}
43+
to={positionReanimatedInterpolated}
44+
/>
45+
<ProgressBarReanimated value={positionReanimatedInterpolated} />
3046
<Boxes
3147
animatedValue={positionAnimated}
3248
sharedValue={positionReanimated}
3349
/>
3450
<Animated.ScrollView
3551
horizontal
36-
contentContainerStyle={[styles.content, { width: width * 2 - 130 }]}
52+
contentContainerStyle={[styles.content, { width: scrollWidth }]}
3753
onScroll={Animated.event(
3854
[{ nativeEvent: { contentOffset: { x: positionAnimated } } }],
3955
{ useNativeDriver: true }
@@ -47,21 +63,38 @@ export function AnimatedToReanimated() {
4763

4864
export function ReanimatedToAnimated() {
4965
const { width } = useWindowDimensions();
66+
67+
const scrollWidth = useScrollWidth();
5068
const scrollRef = useAnimatedRef();
5169

52-
const positionAnimated = useState(() => new Animated.Value(0))[0];
5370
const positionReanimated = useScrollOffset(scrollRef);
71+
const positionAnimated = useState(() => new Animated.Value(0))[0];
72+
73+
const positionReanimatedInterpolated = useDerivedValue(() => {
74+
return interpolate(
75+
positionReanimated.value,
76+
[0, scrollWidth - width],
77+
[1, 0]
78+
);
79+
});
80+
81+
const positionAnimatedInterpolated = useState(() => new Animated.Value(1))[0];
5482

5583
return (
5684
<View style={styles.container}>
5785
<AnimatedConverter from={positionReanimated} to={positionAnimated} />
86+
<AnimatedConverter
87+
from={positionReanimatedInterpolated}
88+
to={positionAnimatedInterpolated}
89+
/>
90+
<ProgressBarAnimated value={positionAnimatedInterpolated} />
5891
<Boxes
5992
animatedValue={positionAnimated}
6093
sharedValue={positionReanimated}
6194
/>
6295
<Animated.ScrollView
6396
horizontal
64-
contentContainerStyle={[styles.content, { width: width * 2 - 130 }]}
97+
contentContainerStyle={[styles.content, { width: scrollWidth }]}
6598
// @ts-expect-error the types are wrong
6699
ref={scrollRef}
67100
>
@@ -133,10 +166,43 @@ function Boxes({
133166
);
134167
}
135168

169+
function ProgressBarAnimated({ value }: { value: Animated.Node }) {
170+
const { width } = useWindowDimensions();
171+
172+
return (
173+
<View style={styles.progressBar}>
174+
<Animated.View
175+
style={[
176+
styles.progress,
177+
{
178+
transform: [{ translateX: Animated.multiply(value, -width) }],
179+
},
180+
]}
181+
/>
182+
</View>
183+
);
184+
}
185+
186+
function ProgressBarReanimated({ value }: { value: SharedValue<number> }) {
187+
const { width } = useWindowDimensions();
188+
189+
const animatedStyle = useAnimatedStyle(() => {
190+
return {
191+
transform: [{ translateX: value.get() * -width }],
192+
};
193+
});
194+
195+
return (
196+
<View style={styles.progressBar}>
197+
<Reanimated.View style={[styles.progress, animatedStyle]} />
198+
</View>
199+
);
200+
}
201+
136202
function ObserverDisplay({
137203
value,
138204
}: {
139-
value: number | Animated.Value | SharedValue<number>;
205+
value: number | Animated.Node | Omit<SharedValue<number>, 'set'>;
140206
}) {
141207
const [displayValue, setDisplayValue] = useState(0);
142208

@@ -153,6 +219,12 @@ function ObserverDisplay({
153219
);
154220
}
155221

222+
function useScrollWidth() {
223+
const { width } = useWindowDimensions();
224+
225+
return width * 2 - 130;
226+
}
227+
156228
function useInterval(callback: () => void, delay: number = 1000) {
157229
const callbackRef = useRef(callback);
158230

@@ -204,9 +276,17 @@ const styles = StyleSheet.create({
204276
color: 'white',
205277
},
206278
reanimated: {
207-
backgroundColor: '#f78c6c',
279+
backgroundColor: '#FF1744',
208280
},
209281
animated: {
210-
backgroundColor: '#82aaff',
282+
backgroundColor: '#304FFE',
283+
},
284+
progressBar: {
285+
height: 3,
286+
overflow: 'hidden',
287+
},
288+
progress: {
289+
height: '100%',
290+
backgroundColor: '#212121',
211291
},
212292
});

src/index.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import Reanimated, {
99
import { default as ObserverView } from './AnimatedObserverViewNativeComponent';
1010

1111
type AnimatedObserverProps = {
12-
value: Animated.Value | SharedValue<number> | number;
12+
value: Animated.Node | Omit<SharedValue<number>, 'set'> | number;
1313
onValueChange: NonNullable<
1414
| React.ComponentProps<typeof ObserverView>['onValueChange']
1515
| React.ComponentProps<typeof AnimatedObserverViewInternal>['onValueChange']
@@ -33,6 +33,7 @@ export function AnimatedObserver({
3333
// @ts-expect-error - component has incorrect type for value prop
3434
<ReanimatedObserverViewInternal tag={tag} value={value} />
3535
) : (
36+
// @ts-expect-error - isSharedValue won't return proper type for derived value
3637
<AnimatedObserverViewInternal tag={tag} value={value} />
3738
)}
3839
{typeof onValueChange === 'function' ? (
@@ -60,6 +61,7 @@ export function AnimatedConverter(props: AnimatedConverterProps) {
6061
}
6162

6263
if (!isSharedValue<number>(props.from) && isSharedValue<number>(props.to)) {
64+
// @ts-expect-error - isSharedValue won't return proper type for derived value
6365
return <AnimatedToReanimated from={props.from} to={props.to} />;
6466
}
6567

@@ -69,7 +71,7 @@ export function AnimatedConverter(props: AnimatedConverterProps) {
6971
}
7072

7173
type AnimatedToReanimatedProps = {
72-
from: Animated.Value;
74+
from: Animated.Node;
7375
to: SharedValue<number>;
7476
};
7577

@@ -104,7 +106,7 @@ function AnimatedToReanimated({
104106
}
105107

106108
type ReanimatedToAnimatedProps = {
107-
from: SharedValue<number>;
109+
from: Omit<SharedValue<number>, 'set'>;
108110
to: Animated.Value;
109111
};
110112

0 commit comments

Comments
 (0)