网站搜索

javascript - Reanimated v2 - 同步共享值


问题

我正在尝试使用 Reanimated v2 创建这个动画:

这是当前的实现:

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);
}, []);

问题是,在我用 // * 标记的代码处,似乎存在一些随机的延迟(可能是由于 JS 执行),导致三个点有时会同步(具有相同的不透明度)。

我猜问题在于更新那三个值不是原子性的,所以在那些赋值之间可能发生任何事情。

解决这个问题的最佳方法是什么,并且如何让这三个共享值之间有确定性的延迟?

我尝试过什么?

  • 我尝试使用 1 个 useSharedValue 和 2 个 useDerivedValue,但是让一个从 0 开始,一个从 0.5 开始,一个从 1 开始的数学计算并不简单(仅仅在它们之间加 0.5 并取模 1 并不能考虑 withRepeat 在达到 1 后回到起点的情况)
  • 我尝试使用 useSharedValue([0, 0, 0]),然后用原子操作更新它,但似乎不支持这样做

答案#1

我找到了解决方案,不确定这是否是最好的,但目前它能用。

这个想法是:

  • 有一个共享的值“progress”,其 0 -> 1 映射到完整的动画周期(例如 0 -> 1 -> 0)
  • 有3个衍生值,它们在不同时间开始并且插值方式不同:

    • 一个 0 -> 0.5 -> 1 -> 0.5 -> 0
    • 一 0.5 -> 1 -> 0.5 -> 0 -> 0.5
    • 一 1 -> 0.5 -> 0 -> 0.5 -> 1

这是代码:

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])
);