Animated๋ ์ ๋๋ฉ์ด์ ์ ์ฝ๊ฒ ๋ง๋ค ์ ์๋๋ก ๋์์ค๋ค.
์ปดํฌ๋ํธ์ ์คํ์ผ, ์์น, ํฌ๋ช ๋ ๋ฑ์ ์์ฑ์ ์ ๋๋ฉ์ด์ ์ผ๋ก ๋ณ๊ฒฝํ๊ณ , ์ ๋๋ฉ์ด์ ์๊ฐ, ํ์ด๋ฐ, ๋ฐ๋ณต ๋ฑ์ ์ธ๋ฐํ๊ฒ ์ ์ดํ ์ ์๋ค.
// ๊ฐ์ ์ง์ ๋ฐ๊พธ๋ฉด ์๋๊ธฐ์ useRef๋ฅผ ์ฌ์ฉํจ
// Value์ ์์ฑ์ ํจ์ ์ธ์์๋ ์ด๊น๊ฐ์ ๋ฃ์ด์ค
const refAnimation = useRef(new Animated.Value(0)).current;
interpolate
: Value๊ฐ ๊ฐ์ง๊ณ ์๋ ๊ฐ์ ๊ธฐ์ค์ผ๋ก ์๋ก์ด ๊ฐ์ ์์ฑ
const widthAnimation = refAnimation.interpolate({
inputRange: [0, 10], // refAnimation์ ๊ฐ์ด 0์์ 10 ์ฌ์ด๋ก ๋ณํํ ์ ์์
outputRange: ['0%', '100%'], // refAnimation์ด 0์ผ ๋๋ '0%'๊ฐ ์์ฑ, ๊ฐ์ด 10์ผ ๋๋ '100%'๊ฐ ์์ฑ
});
...
// Animated ์ฐ๊ฒฐ
<Animated.View style={{ width: widthAnimation }} />
Animated.timing์ ์ด์ฉํด์ Animated Value์ ๊ฐ์ ๋ณ๊ฒฝํ ์ ์๋ค.
Animated.timing(refAnimation, {
toValue: 0, // ์ ๋๋ฉ์ด์
์ ๋ชฉํ, refAnimation์ด ์ด ๊ฐ์ผ๋ก ๋ณํ (ํ์โญ๏ธ)
useNativeDriver: false, // ๋ค์ดํฐ๋ธ ๋๋ผ์ด๋ฒ ์ฌ์ฉ ์ฌ๋ถ
duration: 1000, // ์ ๋๋ฉ์ด์
์ ์ง์ ์๊ฐ์ ๋ฐ๋ฆฌ์ด ๋จ์๋ก ์ง์ - ๊ธฐ๋ณธ๊ฐ 500
delay: 0, // ์ ๋๋ฉ์ด์
์ ์์์ ์ง์ฐ์ํฌ ์๊ฐ
isInteraction: true, // ์ ๋๋ฉ์ด์
์ด ๋ค๋ฅธ ์ํธ์์ฉ๊ณผ ์ํธ์์ฉํ๋์ง ์ฌ๋ถ - ๊ธฐ๋ณธ๊ฐ true
easing: Easing.inOut(Easing.ease), // ์ ๋๋ฉ์ด์
์ ๊ฐ์๋ ํจ์๋ฅผ ์ค์ , Easing ๋ชจ๋์ ์ฌ์ฉํ์ฌ ์ค์ ํจ - ๊ธฐ๋ณธ๊ฐ Easing.inOut(Easing.ease)
}).start(() => {
// ์ ๋๋ฉ์ด์
์ด ์๋ฃ๋์์ ๋ ์คํํ ์์
})
7์ด๋์ ์ผ์ชฝ์์ ์ค๋ฅธ์ชฝ์ผ๋ก ๋ถ๋๋ฝ๊ฒ ์์ง์ด๋ ์ ๋๋ฉ์ด์
import { View, Animated } from 'react-native';
import React, { useEffect, useRef } from 'react';
...
const refAnimation = useRef(new Animated.Value(-380)).current;
useEffect(() => {
Animated.timing(refAnimation, {
toValue: 0,
delay: 0,
duration: 7000,
useNativeDriver: true,
}).start(() => {
navigation.goBack(); // ์ ๋๋ฉ์ด์
์ด ๋๋๋ฉด ๋ค๋ก๊ฐ๊ธฐ ๋จ
});
}, [refAnimation, navigation]);
const animatedStyle = {
height: '100%',
backgroundColor: 'skyblue',
transform: [{translateX: refAnimation}],
};
...
<Animated.View style={animatedStyle} />
const TopImage = ({Img, isScrollable}: Props) => {
const darkmode = isDarkmode();
const notFoundImg = darkmode ? notfoundDarkImg : notfoundLightImg;
const navigation = useNavigation<NativeStackNavigationProp<any>>();
const heightAni = useRef(new Animated.Value(222)).current;
const bgColorAni = useRef(new Animated.Value(0)).current;
useEffect(() => {
Animated.timing(heightAni, {
toValue: isScrollable ? 44 : 222,
duration: 300,
useNativeDriver: false,
}).start();
Animated.timing(bgColorAni, {
toValue: isScrollable ? 0 : 1,
duration: 300,
useNativeDriver: false,
}).start();
}, [isScrollable, heightAni, bgColorAni]);
const backgroundColor = bgColorAni.interpolate({
inputRange: [0, 1],
outputRange: ['rgba(255, 255, 255, 1)', 'rgba(255, 255, 255, 0)'],
});
return (
<Animated.View
style={{height: heightAni, backgroundColor}}
className="relative">
<Animated.View style={{opacity: bgColorAni}}>
<ImageBackground
source={Img ? {uri: Img} : notFoundImg}
resizeMode="cover"
className="h-[222px] w-full"
/>
</Animated.View>
<Pressable
onPress={() => navigation.goBack()}
className="absolute left-[16px] top-[6px]">
<ImageBackground
source={blurBg}
resizeMode="cover"
className="flex justify-center items-center rounded-[8px] w-[32px] h-[32px]">
<LeftArrowIcon />
</ImageBackground>
</Pressable>
</Animated.View>
);
};