import { ThemedText } from '@/components/ThemedText'; import { useI18n } from '@/hooks/useI18n'; import { useThemeColor } from '@/hooks/useThemeColor'; import React, { useEffect, useRef } from 'react'; import { Animated, StyleSheet, View } from 'react-native'; import Svg, { Circle, Defs, Stop, LinearGradient as SvgLinearGradient } from 'react-native-svg'; const AnimatedCircle = Animated.createAnimatedComponent(Circle); export type CalorieRingChartProps = { metabolism: number; exercise: number; consumed: number; protein: number; fat: number; carbs: number; proteinGoal: number; fatGoal: number; carbsGoal: number; }; export function CalorieRingChart({ metabolism, exercise, consumed, protein, fat, carbs, }: CalorieRingChartProps) { const { t } = useI18n(); const textColor = useThemeColor({}, 'text'); const textSecondaryColor = useThemeColor({}, 'textSecondary'); // 动画值 const animatedProgress = useRef(new Animated.Value(0)).current; // 计算还能吃的卡路里:代谢 + 运动 - 饮食 const remainingCalories = metabolism + exercise - consumed; const canEat = Math.max(0, remainingCalories); // 计算进度百分比 (用于圆环显示) const totalAvailable = metabolism + exercise; const progressPercentage = totalAvailable > 0 ? Math.min((consumed / totalAvailable) * 100, 100) : 0; // 圆环参数 - 缩小尺寸 const radius = 42; const strokeWidth = 8; const center = radius + strokeWidth; const circumference = 2 * Math.PI * radius; const strokeDasharray = circumference; // 动画效果 useEffect(() => { Animated.timing(animatedProgress, { toValue: progressPercentage, duration: 600, useNativeDriver: false, }).start(); }, [progressPercentage]); // 使用动画值计算strokeDashoffset const strokeDashoffset = animatedProgress.interpolate({ inputRange: [0, 100], outputRange: [circumference, 0], extrapolate: 'clamp', }); return ( {/* 左侧圆环图 */} 80 ? "#FF9966" : "#4facfe"} stopOpacity="1" /> 80 ? "#FF5E62" : "#00f2fe"} stopOpacity="1" /> {/* 背景圆环 */} {/* 进度圆环 */} {/* 中心内容 */} {t('nutritionRecords.chart.remaining')} {Math.round(canEat)} {t('nutritionRecords.nutrients.caloriesUnit')} {/* 右侧数据展示 - 优化布局 */} {/* 公式 */} {t('nutritionRecords.chart.formula')} {/* 代谢 & 运动 & 饮食 */} {t('nutritionRecords.chart.metabolism')} {Math.round(metabolism)} {t('nutritionRecords.chart.exercise')} {Math.round(exercise)} {t('nutritionRecords.chart.diet')} {Math.round(consumed)} {/* 营养素 - 水平排布 */} {Math.round(protein)}{t('nutritionRecords.nutrients.unit')} {t('nutritionRecords.nutrients.protein')} {Math.round(fat)}{t('nutritionRecords.nutrients.unit')} {t('nutritionRecords.nutrients.fat')} {Math.round(carbs)}{t('nutritionRecords.nutrients.unit')} {t('nutritionRecords.nutrients.carbs')} ); } const styles = StyleSheet.create({ container: { backgroundColor: '#FFFFFF', borderRadius: 24, padding: 16, marginHorizontal: 20, shadowColor: 'rgba(30, 41, 59, 0.08)', shadowOffset: { width: 0, height: 8 }, shadowOpacity: 0.12, shadowRadius: 16, elevation: 6, }, formulaContainer: { marginBottom: 12, }, formulaText: { fontSize: 10, fontWeight: '500', color: '#94A3B8', fontFamily: 'AliRegular', }, mainContent: { flexDirection: 'row', alignItems: 'flex-start', }, chartContainer: { position: 'relative', alignItems: 'center', justifyContent: 'center', width: 100, height: 100, marginTop: 8, }, centerContent: { position: 'absolute', alignItems: 'center', justifyContent: 'center', }, centerLabel: { fontSize: 10, fontWeight: '500', color: '#94A3B8', marginBottom: 1, fontFamily: 'AliRegular', }, centerValue: { fontSize: 20, fontWeight: '800', color: '#1E293B', lineHeight: 24, fontFamily: 'AliBold', }, centerUnit: { fontSize: 10, fontWeight: '600', color: '#64748B', fontFamily: 'AliRegular', }, dataContainer: { flex: 1, marginLeft: 20, }, statsGroup: { gap: 6, }, statRowCompact: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', }, labelWithDot: { flexDirection: 'row', alignItems: 'center', }, dotMetabolism: { width: 6, height: 6, borderRadius: 3, backgroundColor: '#94A3B8', marginRight: 6, }, dotExercise: { width: 6, height: 6, borderRadius: 3, backgroundColor: '#4facfe', marginRight: 6, }, dotConsumed: { width: 6, height: 6, borderRadius: 3, backgroundColor: '#FF9966', marginRight: 6, }, statLabel: { fontSize: 12, color: '#64748B', fontFamily: 'AliRegular', }, statValue: { fontSize: 13, fontWeight: '600', color: '#334155', fontFamily: 'AliBold', }, divider: { height: 1, backgroundColor: '#F1F5F9', marginVertical: 10, }, nutritionRow: { flexDirection: 'row', justifyContent: 'space-between', }, nutritionItem: { alignItems: 'center', }, statLabelSmall: { fontSize: 10, color: '#94A3B8', marginTop: 2, fontFamily: 'AliRegular', }, statValueSmall: { fontSize: 13, fontWeight: '600', color: '#475569', fontFamily: 'AliBold', }, });