如何用单个共享值为多视图设置动画样式(React Native Reanimated)
基于current状态计算React Native Reanimated v3菜单按钮透明度(替代多共享值)
我是React Native Reanimated v3的新手,希望根据当前聚焦的组件为菜单按钮设置透明度样式。目前我的实现代码如下:
type clist = 'one' | 'two' | 'three' const opacityOne = useSharedValue(1) const opacityTwo = useSharedValue(0.4) const opacityThree = useSharedValue(0.4) const [current, setCurrent] = useState<clist>('one') const onPress = (screen:clist) => { setCurrent(screen) switch (screen) { case 'one': opacityOne.value = withTiming(1, {duration: 100}) opacityTwo.value = withTiming(0.4, {duration: 100}) opacityThree.value = withTiming(0.4, {duration: 100}) navigation.navigate('One') break case 'two': opacityOne.value = withTiming(0.4, {duration: 100}) opacityTwo.value = withTiming(1, {duration: 100}) opacityThree.value = withTiming(0.4, {duration: 100}) navigation.navigate('Two') break case 'three': opacityOne.value = withTiming(0.4, {duration: 100}) opacityTwo.value = withTiming(0.4, {duration: 100}) opacityThree.value = withTiming(1, {duration: 100}) navigation.navigate('Three') break } }
我想知道是否可以基于current状态计算opacity,而非使用三个独立的共享值?
当然可以,你只需要维护单个共享值存储当前选中项,然后通过动画样式直接计算每个按钮的透明度,无需多个独立的useSharedValue。以下是两种优化方案:
方案1:同步useState到共享值(兼容非动画逻辑)
适合需要在非动画场景中使用current状态的情况:
type clist = 'one' | 'two' | 'three'; const [current, setCurrent] = useState<clist>('one'); // 单个共享值存储当前选中项 const currentScreen = useSharedValue<clist>(current); // 同步useState更新到共享值,触发透明度动画 useEffect(() => { currentScreen.value = withTiming(current, { duration: 100 }); }, [current]); const onPress = (screen: clist) => { setCurrent(screen); navigation.navigate(screen as never); }; // 为每个按钮生成动画样式 const getAnimatedButtonStyle = (screen: clist) => { return useAnimatedStyle(() => ({ opacity: currentScreen.value === screen ? 1 : 0.4, })); }; // 使用示例: // <Animated.View style={getAnimatedButtonStyle('one')}>...</Animated.View>
方案2:直接用共享值管理状态(更简洁)
如果不需要在非动画逻辑中使用current,可以完全去掉useState,直接用共享值维护选中状态:
type clist = 'one' | 'two' | 'three'; const currentScreen = useSharedValue<clist>('one'); const onPress = (screen: clist) => { // 直接更新共享值,自动触发透明度平滑过渡 currentScreen.value = withTiming(screen, { duration: 100 }); navigation.navigate(screen as never); }; // 单个按钮的动画样式示例 const oneButtonStyle = useAnimatedStyle(() => ({ opacity: currentScreen.value === 'one' ? 1 : 0.4, }));
原理说明
Reanimated会自动跟踪共享值的变化,当currentScreen通过withTiming更新时,所有依赖它的动画样式都会自动完成透明度的平滑过渡,完全替代了原来手动维护三个共享值的冗余逻辑。
内容的提问来源于stack exchange,提问作者Dalton
相关产品推荐
相关产品推荐

