如何在React Native中实现CSS关键帧旋转渐变动画?
在React Native中实现旋转渐变发光卡片动画
核心效果分析
原CSS动画的核心是:
- 深色背景卡片,外层有旋转的渐变边框
- 下层带模糊效果的同渐变层同步旋转
- 鼠标悬停(或触摸)时,文字显现,渐变层停止旋转并淡出
下面基于你已有的react-native-reanimated和native-base实现该效果,额外需要react-native-linear-gradient处理渐变(若未安装,执行npm install react-native-linear-gradient)。
完整代码实现
import React, { useState, useEffect } from 'react'; import { Pressable } from 'react-native'; import { Box, Text } from 'native-base'; import Animated, { useSharedValue, useAnimatedStyle, withRepeat, withTiming } from 'react-native-reanimated'; import LinearGradient from 'react-native-linear-gradient'; const RotatingGradientCard = () => { // 定义卡片尺寸,对应原CSS的自定义变量 const CARD_WIDTH = 300; const CARD_HEIGHT = 400; // 动画状态值 const rotateDegree = useSharedValue(0); const gradientOpacity = useSharedValue(1); const [isActive, setIsActive] = useState(false); // 启动/停止旋转动画 useEffect(() => { if (!isActive) { // 无限循环旋转,2.5秒一圈 rotateDegree.value = withRepeat(withTiming(360, { duration: 2500 }), -1, false); } else { // 停止在当前角度 rotateDegree.value = withTiming(rotateDegree.value); } }, [isActive, rotateDegree]); // 渐变层透明度动画 useEffect(() => { gradientOpacity.value = withTiming(isActive ? 0 : 1, { duration: 500 }); }, [isActive, gradientOpacity]); // 外层渐变边框(对应CSS的:before)的动画样式 const animatedBorderStyle = useAnimatedStyle(() => ({ transform: [{ rotate: `${rotateDegree.value}deg` }], opacity: gradientOpacity.value })); // 下层模糊渐变层(对应CSS的:after)的动画样式 const animatedBlurStyle = useAnimatedStyle(() => ({ transform: [{ rotate: `${rotateDegree.value}deg` }, { scale: 0.8 }], opacity: gradientOpacity.value, // 用阴影模拟模糊效果,若需要更精确可使用@react-native-community/blur shadowColor: '#5ddcff', shadowOffset: { width: 0, height: 0 }, shadowOpacity: 0.8, shadowRadius: CARD_HEIGHT / 6 })); return ( <Pressable // Web端用hover事件,Native端用触摸事件替代 onHoverIn={() => setIsActive(true)} onHoverOut={() => setIsActive(false)} onPressIn={() => setIsActive(true)} onPressOut={() => setIsActive(false)} style={{ justifyContent: 'center', alignItems: 'center', padding: 20 }} > <Box width={CARD_WIDTH} height={CARD_HEIGHT} bg="#191c29" borderRadius={6} justifyContent="center" alignItems="center" position="relative" padding={3} > {/* 外层旋转渐变边框 */} <Animated.View style={[ { position: 'absolute', top: -CARD_HEIGHT * 0.01, left: -CARD_WIDTH * 0.02, width: CARD_WIDTH * 1.04, height: CARD_HEIGHT * 1.02, borderRadius: 8, zIndex: -1 }, animatedBorderStyle ]} > <LinearGradient colors={['#5ddcff', '#3c67e3', '#4e00c2']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={{ flex: 1, borderRadius: 8 }} /> </Animated.View> {/* 下层模糊渐变层 */} <Animated.View style={[ { position: 'absolute', top: CARD_HEIGHT / 6, left: 0, right: 0, width: CARD_WIDTH, height: CARD_HEIGHT, zIndex: -2, alignSelf: 'center' }, animatedBlurStyle ]} > <LinearGradient colors={['#5ddcff', '#3c67e3', '#4e00c2']} start={{ x: 0, y: 0 }} end={{ x: 1, y: 1 }} style={{ flex: 1, borderRadius: 6 }} /> </Animated.View> {/* 卡片文字 */} <Text fontSize="1.5em" color={isActive ? 'rgba(88,199,250,1)' : 'rgba(88,199,250,0)'} fontFamily="cursive" transition="color 1000ms" > Hover Me! </Text> </Box> </Pressable> ); }; export default RotatingGradientCard;
关键细节说明
- 伪元素替代:React Native没有CSS伪元素,用两个绝对定位的
Animated.View分别模拟:before和:after的效果。 - 旋转动画:通过
react-native-reanimated的withRepeat和withTiming实现无限循环旋转,激活时停止在当前角度。 - 模糊效果:原CSS的
filter: blur用阴影近似模拟,若需要更精确的模糊效果,可安装@react-native-community/blur并替换阴影部分为BlurView。 - 跨平台适配:Web端使用
onHoverIn/onHoverOut,Native端用onPressIn/onPressOut替代hover交互,保证多平台可用。 - 文字过渡:通过
native-base的transition属性实现文字颜色的平滑过渡,与原CSS效果一致。
内容的提问来源于stack exchange,提问作者user2921885
相关产品推荐
相关产品推荐

