Kantongku: animasi bar Uangmu Nyawamu (smooth width + shimmer + pulse kritis)
This commit is contained in:
@@ -48,6 +48,9 @@ export function DashboardScreen() {
|
||||
const [compare, setCompare] = useState({ current: 0, previous: 0 });
|
||||
const [hidden, setHidden] = useState(true);
|
||||
const heartScale = useRef(new Animated.Value(1)).current;
|
||||
const hpAnim = useRef(new Animated.Value(0)).current;
|
||||
const shimmerX = useRef(new Animated.Value(-140)).current;
|
||||
const pulse = useRef(new Animated.Value(1)).current;
|
||||
|
||||
useEffect(() => {
|
||||
const loop = Animated.loop(
|
||||
@@ -67,6 +70,53 @@ export function DashboardScreen() {
|
||||
loop.start();
|
||||
return () => loop.stop();
|
||||
}, [heartScale]);
|
||||
|
||||
// Bar HP: width bergerak halus mengikuti data
|
||||
useEffect(() => {
|
||||
Animated.timing(hpAnim, {
|
||||
toValue: hpPct,
|
||||
duration: 800,
|
||||
useNativeDriver: false,
|
||||
}).start();
|
||||
}, [hpPct, hpAnim]);
|
||||
|
||||
// Shimmer: kilau menyapu di atas bar
|
||||
useEffect(() => {
|
||||
const loop = Animated.loop(
|
||||
Animated.timing(shimmerX, {
|
||||
toValue: 480,
|
||||
duration: 2200,
|
||||
useNativeDriver: true,
|
||||
})
|
||||
);
|
||||
loop.start();
|
||||
return () => loop.stop();
|
||||
}, [shimmerX]);
|
||||
|
||||
// Denyut saat kritis
|
||||
useEffect(() => {
|
||||
let loop: Animated.CompositeAnimation | null = null;
|
||||
if (hpPct < 40) {
|
||||
loop = Animated.loop(
|
||||
Animated.sequence([
|
||||
Animated.timing(pulse, {
|
||||
toValue: 0.5,
|
||||
duration: 480,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
Animated.timing(pulse, {
|
||||
toValue: 1,
|
||||
duration: 480,
|
||||
useNativeDriver: true,
|
||||
}),
|
||||
])
|
||||
);
|
||||
loop.start();
|
||||
} else {
|
||||
pulse.setValue(1);
|
||||
}
|
||||
return () => loop?.stop();
|
||||
}, [hpPct, pulse]);
|
||||
const [monthExpense, setMonthExpense] = useState(0);
|
||||
const [monthIncome, setMonthIncome] = useState(0);
|
||||
const [topCategory, setTopCategory] = useState<{
|
||||
@@ -343,12 +393,32 @@ export function DashboardScreen() {
|
||||
<Text style={[styles.hpPct, { color: hpColor }]}>{hpPct}%</Text>
|
||||
</View>
|
||||
<View style={styles.hpTrack}>
|
||||
<View
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.hpFill,
|
||||
{ width: `${hpPct}%`, backgroundColor: hpBarColor },
|
||||
{
|
||||
backgroundColor: hpBarColor,
|
||||
width: hpAnim.interpolate({
|
||||
inputRange: [0, 100],
|
||||
outputRange: ['0%', '100%'],
|
||||
}),
|
||||
opacity: pulse,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.shimmer,
|
||||
{ transform: [{ translateX: shimmerX }] },
|
||||
]}
|
||||
>
|
||||
<LinearGradient
|
||||
colors={['transparent', 'rgba(255,255,255,0.45)', 'transparent']}
|
||||
start={{ x: 0, y: 0 }}
|
||||
end={{ x: 1, y: 0 }}
|
||||
style={styles.shimmerGradient}
|
||||
/>
|
||||
</Animated.View>
|
||||
</View>
|
||||
<View style={styles.hpFooter}>
|
||||
<Text style={[styles.hpStatus, { color: hpColor }]}>{hpStatus}</Text>
|
||||
@@ -874,6 +944,14 @@ const styles = StyleSheet.create({
|
||||
height: '100%',
|
||||
borderRadius: 7,
|
||||
},
|
||||
shimmer: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
width: '45%',
|
||||
},
|
||||
shimmerGradient: { flex: 1 },
|
||||
hpFooter: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
|
||||
Reference in New Issue
Block a user