feat: 优化数据加载逻辑,添加应用状态监听以刷新统计数据;为步数卡片添加动画效果
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import React, { useMemo, useRef, useEffect } from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View,
|
||||
ViewStyle
|
||||
ViewStyle,
|
||||
Animated
|
||||
} from 'react-native';
|
||||
|
||||
import { HourlyStepData } from '@/utils/health';
|
||||
@@ -23,6 +24,11 @@ const StepsCard: React.FC<StepsCardProps> = ({
|
||||
hourlySteps,
|
||||
style
|
||||
}) => {
|
||||
// 为每个柱体创建独立的动画值
|
||||
const animatedValues = useRef(
|
||||
Array.from({ length: 24 }, () => new Animated.Value(0))
|
||||
).current;
|
||||
|
||||
// 计算柱状图数据
|
||||
const chartData = useMemo(() => {
|
||||
if (!hourlySteps || hourlySteps.length === 0) {
|
||||
@@ -42,6 +48,26 @@ const StepsCard: React.FC<StepsCardProps> = ({
|
||||
// 获取当前小时
|
||||
const currentHour = new Date().getHours();
|
||||
|
||||
// 触发柱体动画
|
||||
useEffect(() => {
|
||||
if (chartData && chartData.length > 0) {
|
||||
// 重置所有动画值
|
||||
animatedValues.forEach(animValue => animValue.setValue(0));
|
||||
|
||||
// 同时启动所有柱体的弹性动画,有步数的柱体才执行动画
|
||||
chartData.forEach((data, index) => {
|
||||
if (data.steps > 0) {
|
||||
Animated.spring(animatedValues[index], {
|
||||
toValue: 1,
|
||||
tension: 150,
|
||||
friction: 8,
|
||||
useNativeDriver: false,
|
||||
}).start();
|
||||
}
|
||||
});
|
||||
}
|
||||
}, [chartData, animatedValues]);
|
||||
|
||||
return (
|
||||
<View style={[styles.container, style]}>
|
||||
{/* 标题和步数显示 */}
|
||||
@@ -58,14 +84,28 @@ const StepsCard: React.FC<StepsCardProps> = ({
|
||||
const isActive = data.steps > 0;
|
||||
const isCurrent = index <= currentHour;
|
||||
|
||||
// 动画变换:缩放从0到实际高度
|
||||
const animatedScale = animatedValues[index].interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
});
|
||||
|
||||
// 动画变换:透明度从0到1
|
||||
const animatedOpacity = animatedValues[index].interpolate({
|
||||
inputRange: [0, 1],
|
||||
outputRange: [0, 1],
|
||||
});
|
||||
|
||||
return (
|
||||
<View
|
||||
<Animated.View
|
||||
key={`bar-${index}`}
|
||||
style={[
|
||||
styles.chartBar,
|
||||
{
|
||||
height: data.height || 2, // 最小高度2px
|
||||
backgroundColor: isCurrent && isActive ? '#FFC365' : '#FFEBCB',
|
||||
transform: [{ scaleY: animatedScale }],
|
||||
opacity: animatedOpacity,
|
||||
}
|
||||
]}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user