feat: 优化营养记录和卡路里环图组件,增加毛玻璃背景和动画效果

This commit is contained in:
richarjiang
2025-09-04 11:28:31 +08:00
parent 4ae419754a
commit 5e00cb7788
6 changed files with 302 additions and 254 deletions

View File

@@ -11,21 +11,18 @@ export type CalorieRingChartProps = {
metabolism: number;
exercise: number;
consumed: number;
goal: number;
protein: number;
fat: number;
carbs: number;
proteinGoal: number;
fatGoal: number;
carbsGoal: number;
};
export function CalorieRingChart({
metabolism,
exercise,
consumed,
goal,
protein,
fat,
carbs,
@@ -49,9 +46,9 @@ export function CalorieRingChart({
const totalAvailable = metabolism + exercise;
const progressPercentage = totalAvailable > 0 ? Math.min((consumed / totalAvailable) * 100, 100) : 0;
// 圆环参数 - 更小的圆环以适应布局
const radius = 62;
const strokeWidth = 6;
// 圆环参数 - 减小尺寸以优化空间占用
const radius = 48;
const strokeWidth = 8; // 增加圆环厚度
const center = radius + strokeWidth;
const circumference = 2 * Math.PI * radius;
const strokeDasharray = circumference;
@@ -100,7 +97,7 @@ export function CalorieRingChart({
cx={center}
cy={center}
r={radius}
stroke={progressPercentage > 80 ? "#FF6B6B" : "#E0E0E0"}
stroke={progressPercentage > 80 ? "#FF6B6B" : "#4ECDC4"}
strokeWidth={strokeWidth}
fill="none"
strokeDasharray={`${strokeDasharray}`}
@@ -116,7 +113,7 @@ export function CalorieRingChart({
</ThemedText>
<ThemedText style={[styles.centerValue, { color: textColor }]}>
{canEat.toFixed(1)}
{Math.round(canEat)}
</ThemedText>
<ThemedText style={[styles.centerPercentage, { color: textSecondaryColor }]}>
{Math.round(progressPercentage)}%
@@ -126,59 +123,58 @@ export function CalorieRingChart({
{/* 右侧数据展示 */}
<View style={styles.dataContainer}>
{/* 各项数值 */}
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(metabolism)}
</ThemedText>
<View style={styles.dataBackground}>
{/* 左右两列布局 */}
<View style={styles.dataColumns}>
{/* 左列:卡路里数据 */}
<View style={styles.dataColumn}>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(metabolism)}
</ThemedText>
</View>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(exercise)}
</ThemedText>
</View>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(consumed)}
</ThemedText>
</View>
</View>
{/* 右列:营养数据 */}
<View style={styles.dataColumn}>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(protein)}g
</ThemedText>
</View>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(fat)}g
</ThemedText>
</View>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(carbs)}g
</ThemedText>
</View>
</View>
</View>
</View>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(exercise)}
</ThemedText>
</View>
<View style={styles.dataItem}>
<ThemedText style={[styles.dataLabel, { color: textSecondaryColor }]}></ThemedText>
<ThemedText style={[styles.dataValue, { color: textColor }]}>
{Math.round(consumed)}
</ThemedText>
</View>
</View>
</View>
{/* 底部营养素展示 */}
<View style={styles.nutritionContainer}>
<View style={styles.nutritionItem}>
<ThemedText style={[styles.nutritionLabel, { color: textSecondaryColor }]}>
</ThemedText>
<ThemedText style={[styles.nutritionValue, { color: textColor }]}>
{Math.round(protein)}/{Math.round(proteinGoal)}g
</ThemedText>
</View>
<View style={styles.nutritionItem}>
<ThemedText style={[styles.nutritionLabel, { color: textSecondaryColor }]}>
</ThemedText>
<ThemedText style={[styles.nutritionValue, { color: textColor }]}>
{Math.round(fat)}/{Math.round(fatGoal)}g
</ThemedText>
</View>
<View style={styles.nutritionItem}>
<ThemedText style={[styles.nutritionLabel, { color: textSecondaryColor }]}>
</ThemedText>
<ThemedText style={[styles.nutritionValue, { color: textColor }]}>
{Math.round(carbs)}/{Math.round(carbsGoal)}g
</ThemedText>
</View>
</View>
</View>
@@ -213,14 +209,14 @@ const styles = StyleSheet.create({
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
marginBottom: 16,
marginBottom: 0, // 移除底部间距,因为不再有底部营养容器
paddingHorizontal: 8,
},
chartContainer: {
position: 'relative',
alignItems: 'center',
justifyContent: 'center',
width: 140,
width: 112, // 减少宽度以匹配更小的圆环 (48*2 + 8*2)
flexShrink: 0,
},
centerContent: {
@@ -235,8 +231,8 @@ const styles = StyleSheet.create({
marginBottom: 2,
},
centerValue: {
fontSize: 16,
fontWeight: '700',
fontSize: 14,
fontWeight: '600',
color: '#333333',
marginBottom: 1,
},
@@ -247,15 +243,29 @@ const styles = StyleSheet.create({
},
dataContainer: {
flex: 1,
marginLeft: 32,
marginLeft: 16,
},
dataBackground: {
backgroundColor: 'rgba(248, 250, 252, 0.8)', // 毛玻璃背景色
borderRadius: 12,
padding: 12,
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 1,
},
shadowOpacity: 0.06,
shadowRadius: 3,
elevation: 1,
// 添加边框增强毛玻璃效果
borderWidth: 0.5,
borderColor: 'rgba(255, 255, 255, 0.8)',
gap: 4,
paddingLeft: 8,
},
dataItem: {
flexDirection: 'row',
alignItems: 'center',
gap: 4,
paddingVertical: 2,
},
dataIcon: {
width: 6,
@@ -273,26 +283,13 @@ const styles = StyleSheet.create({
fontWeight: '600',
color: '#333333',
},
nutritionContainer: {
dataColumns: {
flexDirection: 'row',
justifyContent: 'space-between',
paddingTop: 12,
borderTopWidth: 1,
borderTopColor: 'rgba(0,0,0,0.06)',
gap: 12,
},
nutritionItem: {
alignItems: 'center',
dataColumn: {
flex: 1,
},
nutritionLabel: {
fontSize: 10,
fontWeight: '500',
color: '#999999',
marginBottom: 3,
},
nutritionValue: {
fontSize: 11,
fontWeight: '600',
color: '#333333',
gap: 4,
},
});