feat: 支持饮水记录卡片

This commit is contained in:
richarjiang
2025-09-02 15:50:35 +08:00
parent ed694f6142
commit 85a3c742df
16 changed files with 2066 additions and 56 deletions

View File

@@ -12,36 +12,71 @@ type AnimatedNumberProps = {
export function AnimatedNumber({
value,
durationMs = 800,
durationMs = 300,
format,
style,
resetToken,
}: AnimatedNumberProps) {
const animated = useRef(new Animated.Value(0)).current;
const opacity = useRef(new Animated.Value(1)).current;
const [display, setDisplay] = useState<string>('0');
const [currentValue, setCurrentValue] = useState(0);
useEffect(() => {
animated.stopAnimation(() => {
animated.setValue(0);
Animated.timing(animated, {
toValue: value,
duration: durationMs,
easing: Easing.out(Easing.cubic),
// 如果值没有变化,不执行动画
if (value === currentValue && resetToken === undefined) {
return;
}
// 停止当前动画
opacity.stopAnimation(() => {
// 创建优雅的透明度变化动画
const fadeOut = Animated.timing(opacity, {
toValue: 0.2, // 淡出到较低透明度
duration: durationMs * 0.4, // 淡出占总时长的40%
easing: Easing.out(Easing.quad),
useNativeDriver: false,
}).start();
});
const fadeIn = Animated.timing(opacity, {
toValue: 1,
duration: durationMs * 0.6, // 淡入占总时长的60%
easing: Easing.out(Easing.quad),
useNativeDriver: false,
});
// 在淡出完成时更新数字显示
fadeOut.start(() => {
// 更新当前值和显示
setCurrentValue(value);
setDisplay(format ? format(value) : `${Math.round(value)}`);
// 然后淡入新数字
fadeIn.start();
});
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [value, resetToken]);
// 初始化显示值
useEffect(() => {
const id = animated.addListener(({ value: v }) => {
const num = Number(v) || 0;
setDisplay(format ? format(num) : `${Math.round(num)}`);
});
return () => animated.removeListener(id);
}, [animated, format]);
if (currentValue !== value) {
setCurrentValue(value);
setDisplay(format ? format(value) : `${Math.round(value)}`);
}
}, [value, format, currentValue]);
return <Animated.Text style={style}>{display}</Animated.Text>;
return (
<Animated.Text
style={[
style,
{
opacity: opacity
}
]}
>
{display}
</Animated.Text>
);
}