如何在React Native(Expo)中创建渐变动画?
在Expo React Native中实现循环渐变背景动画(React Native Skia + Reanimated方案)
核心思路
网页端CSS渐变动画的本质是让渐变的颜色停止点循环偏移,在React Native Skia中,我们可以通过Reanimated驱动渐变的颜色位置参数,实现相同的无限循环渐变效果。
实现步骤与代码示例
- 安装依赖
确保你的Expo项目已安装所需依赖:
npx expo install @shopify/react-native-skia react-native-reanimated
同时在babel.config.js中添加Reanimated插件(添加后需重启Metro服务):
module.exports = function(api) { api.cache(true); return { presets: ['babel-preset-expo'], plugins: ['react-native-reanimated/plugin'], }; };
- 完整组件代码
import React from 'react'; import { View } from 'react-native'; import { Canvas, LinearGradient } from '@shopify/react-native-skia'; import Animated, { useSharedValue, useAnimatedStyle, withRepeat, withTiming, Easing } from 'react-native-reanimated'; // 将Skia的LinearGradient包装为可动画组件 const AnimatedLinearGradient = Animated.createAnimatedComponent(LinearGradient); export default function AnimatedGradientBackground() { // 控制渐变偏移的动画值,范围0-1循环 const offset = useSharedValue(0); React.useEffect(() => { // 启动12秒无限循环动画,反向循环实现ease-in-out效果 offset.value = withRepeat( withTiming(1, { duration: 12000, easing: Easing.inOut(Easing.ease), }), -1, true ); }, []); // 动态计算渐变的颜色与位置 const animatedGradientStyle = useAnimatedStyle(() => { const baseColors = ['#ff0000', '#00ff00', '#0000ff', '#ffff00']; // 计算每个颜色的偏移位置,取模1实现循环 let positions = baseColors.map((_, idx) => ((idx / 3) + offset.value) % 1); // 排序位置与对应颜色,保证渐变顺序正确 const sortedPairs = positions.map((pos, idx) => ({ pos, color: baseColors[idx] })) .sort((a, b) => a.pos - b.pos); return { positions: sortedPairs.map(p => p.pos), colors: sortedPairs.map(p => p.color), }; }); return ( <View style={{ flex: 1 }}> <Canvas style={{ flex: 1 }}> <AnimatedLinearGradient start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} // 对应CSS的45deg渐变方向 style={animatedGradientStyle} /> </Canvas> </View> ); }
关键逻辑说明
- 用
useSharedValue创建动画驱动值offset,通过withRepeat和withTiming实现12秒的无限往返循环,匹配网页端的动画时长与缓动效果。 - 在
useAnimatedStyle中,让每个颜色的停止点位置随offset偏移,通过取模1实现循环滚动;之后对位置和颜色进行排序,避免渐变顺序混乱。 - 通过
Animated.createAnimatedComponent包装Skia的LinearGradient,使其能响应Reanimated的动画样式。
内容的提问来源于stack exchange,提问作者Abhishek Mhatre
相关产品推荐
相关产品推荐

