React Native Reanimated
Суурь Animated API-аас илүү гөлгөр, хурдан animation хийхэд react-native-reanimated хэрэглэнэ. Гол давуу тал нь animation бүхэлдээ UI thread дээр ажилладаг тул JavaScript thread удааширсан ч animation тасалдахгүй. Орчин үеийн аппуудад Reanimated бол стандарт болсон.
Суулгах ба тохируулга
npx expo install react-native-reanimated
babel.config.js файлд plugin нэмнэ — энэ алхмыг орхивол ажиллахгүй:
module.exports = function (api) {
api.cache(true);
return {
presets: ["babel-preset-expo"],
plugins: ["react-native-reanimated/plugin"],
};
};
Тохируулсаны дараа npx expo start --clear ажиллуулж cache цэвэрлэнэ.
useSharedValue ба useAnimatedStyle
Reanimated-н гол ойлголт хоёр hook дээр суурилдаг:
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withSpring,
} from 'react-native-reanimated';
import { TouchableOpacity, View, Text, StyleSheet } from 'react-native';
export default function ReanimatedExample() {
// useSharedValue нь UI thread дээр ажилладаг утга
const scale = useSharedValue(1);
const opacity = useSharedValue(1);
// useAnimatedStyle нь shared value-г style болгоно
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
opacity: opacity.value,
}));
function handlePress() {
scale.value = withSpring(1.2, {}, () => {
scale.value = withSpring(1);
});
opacity.value = withTiming(0.7, { duration: 150 }, () => {
opacity.value = withTiming(1, { duration: 150 });
});
}
return (
<View style={styles.container}>
<TouchableOpacity onPress={handlePress}>
<Animated.View style={[styles.card, animatedStyle]}>
<Text style={styles.emoji}>🚀</Text>
<Text style={styles.label}>Дар!</Text>
</Animated.View>
</TouchableOpacity>
</View>
);
}
const styles = StyleSheet.create({
container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#0b1120' },
card: { width: 140, height: 140, backgroundColor: '#0f172a', borderRadius: 20, justifyContent: 'center', alignItems: 'center', borderWidth: 1, borderColor: '#22d3ee' },
emoji: { fontSize: 48 },
label: { color: '#94a3b8', marginTop: 8 },
});
useSharedValue нь useRef(new Animated.Value()) шиг боловч UI thread дээр шууд ажилладаг. useAnimatedStyle дотор scale.value гэж утгыг унших нь автоматаар reactive болдог.
Scroll-тай хослуулсан animation
Scroll хийхэд header жижгэрэх, алга болох animation маш түгээмэл:
import Animated, {
useSharedValue,
useAnimatedStyle,
useAnimatedScrollHandler,
interpolate,
Extrapolation,
} from 'react-native-reanimated';
const HEADER_HEIGHT = 200;
export default function ParallaxScreen() {
const scrollY = useSharedValue(0);
const scrollHandler = useAnimatedScrollHandler({
onScroll: (event) => {
scrollY.value = event.contentOffset.y;
},
});
const headerStyle = useAnimatedStyle(() => {
const height = interpolate(
scrollY.value,
[0, HEADER_HEIGHT],
[HEADER_HEIGHT, 60],
Extrapolation.CLAMP
);
const opacity = interpolate(
scrollY.value,
[0, HEADER_HEIGHT / 2],
[1, 0],
Extrapolation.CLAMP
);
return { height, opacity };
});
return (
<View style={{ flex: 1, backgroundColor: '#0b1120' }}>
<Animated.View style={[{ backgroundColor: '#22d3ee', justifyContent: 'center', alignItems: 'center' }, headerStyle]}>
<Text style={{ color: '#0b1120', fontSize: 22, fontWeight: 'bold' }}>Миний апп</Text>
</Animated.View>
<Animated.ScrollView onScroll={scrollHandler} scrollEventThrottle={16}>
{Array.from({ length: 20 }, (_, i) => (
<View key={i} style={{ padding: 16, borderBottomWidth: 1, borderBottomColor: '#1e293b' }}>
<Text style={{ color: '#f1f5f9' }}>Жагсаалтын мөр {i + 1}</Text>
</View>
))}
</Animated.ScrollView>
</View>
);
}
withTiming, withSpring, withRepeat
Reanimated-д animation хийх олон арга бий:
import Animated, {
useSharedValue,
useAnimatedStyle,
withTiming,
withSpring,
withRepeat,
withSequence,
Easing,
} from 'react-native-reanimated';
export default function AnimationTypesDemo() {
const rotation = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ rotate: `${rotation.value}deg` }],
}));
function spin() {
// Тогтмол эргэх
rotation.value = withRepeat(
withTiming(360, { duration: 1000, easing: Easing.linear }),
-1, // -1 = хязгааргүй давталт
false
);
}
function shake() {
// Чичрэх
rotation.value = withSequence(
withTiming(-10, { duration: 50 }),
withTiming(10, { duration: 50 }),
withTiming(-10, { duration: 50 }),
withTiming(0, { duration: 50 })
);
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#0b1120' }}>
<Animated.View style={[{ width: 80, height: 80, backgroundColor: '#a78bfa', borderRadius: 12 }, animatedStyle]} />
<TouchableOpacity onPress={spin} style={{ marginTop: 24, padding: 12, backgroundColor: '#1e293b', borderRadius: 8 }}>
<Text style={{ color: '#f1f5f9' }}>Эргүүлэх</Text>
</TouchableOpacity>
<TouchableOpacity onPress={shake} style={{ marginTop: 8, padding: 12, backgroundColor: '#1e293b', borderRadius: 8 }}>
<Text style={{ color: '#f1f5f9' }}>Чичрүүлэх</Text>
</TouchableOpacity>
</View>
);
}
Reanimated маш хүчирхэг боловч суурь ойлголт нь энгийн — useSharedValue + useAnimatedStyle хоёрыг сайн ойлгосон бол бусад нь цаашид өөрөө ойлгогдоно.
Дараагийн хичээлд:
Gesture Handler — хуруугаараа дарах, чирэх, pinch zoom хийх зэрэг gesture-үүдийг animation-тай хослуулах талаар сурна. Reanimated болон Gesture Handler хамтдаа ашиглахад апп маш мэргэжлийн болдог.