feat: 支持饮水记录卡片
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user