I'm trying to create this animation using Reanimated v2:
This is the current implementation:
const opacity1 = useSharedValue(0);
const opacity2 = useSharedValue(0);
const opacity3 = useSharedValue(0);
useEffect(() => {
const duration = 600;
const timingOptions = { duration: duration };
const pulse = withTiming(1, timingOptions);
const repeated = withRepeat(pulse, -1, true);
opacity1.value = repeated;
// *
opacity2.value = withDelay(duration / 2, repeated);
// *
opacity3.value = withDelay(duration, repeated);
}, []);
The problem is that where I've marked the code with // *
there seem to be some random delay (probably due to the JS execution) that cause the three dots to sometimes end up in sync (having the same opacity).
I presume the problem is that updating those 3 values is not atomic, so anything can happen in between those assignments.
What's the best way to solve this and have those 3 shared values with a deterministic delay between each other?
useSharedValue
and 2 useDerivedValue
s but the math to get one to start at 0, one to start at 0.5, and one to start at 1 is non trivial (just adding 0.5 between each other and moduling it (%) to 1 doesn't account for the withRepeat
going back after reaching 1)useSharedValue([0, 0, 0])
and then updating it with an atomic operation, but that doesn't seem to be supportedI've found a solution, not sure if it's the best one but it currently works.
The idea is:
and here's the code:
const progress = useSharedValue(0);
useEffect(() => {
const pulse = withTiming(1, { duration: 1200, easing: Easing.linear });
progress.value = withRepeat(pulse, -1, false);
}, []);
const opacity1 = useDerivedValue(() =>
interpolate(progress.value, [0, 0.25, 0.5, 0.75, 1], [0, 0.5, 1, 0.5, 0])
);
const opacity2 = useDerivedValue(() =>
interpolate(progress.value, [0, 0.25, 0.5, 0.75, 1], [0.5, 1, 0.5, 0, 0.5])
);
const opacity3 = useDerivedValue(() =>
interpolate(progress.value, [0, 0.25, 0.5, 0.75, 1], [1, 0.5, 0, 0.5, 1])
);