You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Native中同一组件实现Reanimated2两种退场动画求助

用Reanimated实现卡片的淡出位移动画

核心实现思路

  • 用Reanimated的SharedValue跟踪动画状态(透明度、位移参数)
  • 点击按钮时通过withTiming触发并行的淡出+位移动画
  • 借助useAnimatedStyle将动画值映射为组件的实时样式

完整代码示例

import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { useSharedValue, useAnimatedStyle, withTiming, Animated } from 'react-native-reanimated';

const AnimatedCard = () => {
  // 初始化动画状态变量
  const opacity = useSharedValue(1);
  const translateY = useSharedValue(0);
  const translateX = useSharedValue(0);

  // 生成动画样式
  const animatedCardStyle = useAnimatedStyle(() => {
    return {
      opacity: opacity.value,
      transform: [
        { translateY: translateY.value },
        { translateX: translateX.value }
      ]
    };
  });

  // Dismiss按钮逻辑:淡出+上移动画
  const handleDismiss = () => {
    // 同步执行透明度降低与向上位移
    opacity.value = withTiming(0, { duration: 300 });
    translateY.value = withTiming(-50, { duration: 300 });
    
    // 可选:动画结束后重置卡片状态(如需复用卡片)
    setTimeout(() => {
      opacity.value = withTiming(1, { duration: 0 });
      translateY.value = withTiming(0, { duration: 0 });
    }, 400);
  };

  // Follow按钮逻辑:淡出+左移动画
  const handleFollow = () => {
    opacity.value = withTiming(0, { duration: 300 });
    translateX.value = withTiming(-300, { duration: 300 });
    
    // 可选:动画结束后重置卡片状态
    setTimeout(() => {
      opacity.value = withTiming(1, { duration: 0 });
      translateX.value = withTiming(0, { duration: 0 });
    }, 400);
  };

  return (
    <View style={styles.container}>
      <Animated.View style={[styles.card, animatedCardStyle]}>
        <Text style={styles.cardText}>示例卡片内容</Text>
        <View style={styles.buttonContainer}>
          <TouchableOpacity style={styles.followBtn} onPress={handleFollow}>
            <Text style={styles.btnText}>Follow</Text>
          </TouchableOpacity>
          <TouchableOpacity style={styles.dismissBtn} onPress={handleDismiss}>
            <Text style={styles.btnText}>Dismiss</Text>
          </TouchableOpacity>
        </View>
      </Animated.View>
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
  },
  card: {
    width: '100%',
    padding: 20,
    backgroundColor: '#fff',
    borderRadius: 8,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 3,
  },
  cardText: {
    fontSize: 16,
    marginBottom: 16,
  },
  buttonContainer: {
    flexDirection: 'row',
    justifyContent: 'flex-end',
    gap: 12,
  },
  followBtn: {
    paddingHorizontal: 16,
    paddingVertical: 8,
    backgroundColor: '#007AFF',
    borderRadius: 4,
  },
  dismissBtn: {
    paddingHorizontal: 16,
    paddingVertical: 8,
    backgroundColor: '#FF3B30',
    borderRadius: 4,
  },
  btnText: {
    color: '#fff',
    fontSize: 14,
  },
});

export default AnimatedCard;

关键细节说明

  • 并行动画:直接同时更新opacity和位移的SharedValue,Reanimated会自动同步执行两个动画
  • 动画参数调整:withTiming的第二个参数可配置时长、缓动函数,比如ease、spring,按需修改效果
  • 动态位移边界:如果需要左移动画完全移出屏幕,可通过useWindowDimensions获取屏幕宽度,将translateX目标值设为-screenWidth
  • 组件销毁逻辑:如果动画结束后需要移除卡片,可监听opacity值变化,当变为0时通过状态控制组件渲染

内容的提问来源于stack exchange,提问作者Hyzam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 11:24:35