乐闻世界logo
搜索文章和话题

How to implement animations in Expo? What are the common animation libraries?

2月21日 16:03

Expo animations are an important means to enhance user experience. Expo supports multiple animation libraries and APIs, with comprehensive solutions from simple transition effects to complex interactive animations.

Animation Library Selection:

  1. React Native Animated API

React Native's built-in animation API, suitable for most animation needs.

Basic Animation:

typescript
import { Animated, Easing } from 'react-native'; function FadeInComponent() { const fadeAnim = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.timing(fadeAnim, { toValue: 1, duration: 1000, easing: Easing.ease, useNativeDriver: true, }).start(); }, []); return ( <Animated.View style={{ opacity: fadeAnim }}> <Text>Fade In</Text> </Animated.View> ); }

Interpolation Animation:

typescript
function InterpolationComponent() { const translateX = useRef(new Animated.Value(0)).current; const rotate = translateX.interpolate({ inputRange: [0, 100], outputRange: ['0deg', '180deg'], }); const scale = translateX.interpolate({ inputRange: [0, 100], outputRange: [1, 2], }); return ( <Animated.View style={{ transform: [ { translateX }, { rotate }, { scale }, ], }} > <Text>Animated Box</Text> </Animated.View> ); }

Parallel and Sequence Animations:

typescript
function ComplexAnimation() { const fadeAnim = useRef(new Animated.Value(0)).current; const scaleAnim = useRef(new Animated.Value(1)).current; const startAnimation = () => { Animated.parallel([ Animated.timing(fadeAnim, { toValue: 1, duration: 500, useNativeDriver: true, }), Animated.spring(scaleAnim, { toValue: 1.5, friction: 5, useNativeDriver: true, }), ]).start(); }; return ( <Animated.View style={{ opacity: fadeAnim, transform: [{ scale: scaleAnim }], }} > <Button title="Animate" onPress={startAnimation} /> </Animated.View> ); }
  1. React Native Reanimated

More powerful animation library, supports gestures and complex animations.

Installation:

bash
npx expo install react-native-reanimated

Basic Animation:

typescript
import Animated, { useSharedValue, useAnimatedStyle, withTiming, withSpring, withSequence, } from 'react-native-reanimated'; function ReanimatedComponent() { const opacity = useSharedValue(0); const scale = useSharedValue(1); const animatedStyle = useAnimatedStyle(() => { return { opacity: opacity.value, transform: [{ scale: scale.value }], }; }); const startAnimation = () => { opacity.value = withTiming(1, { duration: 500 }); scale.value = withSpring(1.5); }; return ( <Animated.View style={animatedStyle}> <Button title="Animate" onPress={startAnimation} /> </Animated.View> ); }

Gesture Animation:

typescript
import { Gesture, GestureDetector } from 'react-native-gesture-handler'; function GestureComponent() { const translateX = useSharedValue(0); const translateY = useSharedValue(0); const pan = Gesture.Pan() .onUpdate((event) => { translateX.value = event.translationX; translateY.value = event.translationY; }) .onEnd(() => { translateX.value = withSpring(0); translateY.value = withSpring(0); }); const animatedStyle = useAnimatedStyle(() => { return { transform: [ { translateX: translateX.value }, { translateY: translateY.value }, ], }; }); return ( <GestureDetector gesture={pan}> <Animated.View style={animatedStyle}> <Text>Drag me</Text> </Animated.View> </GestureDetector> ); }
  1. Lottie

Complex animations created with Adobe After Effects.

Installation:

bash
npx expo install lottie-react-native

Using Lottie Animations:

typescript
import LottieView from 'lottie-react-native'; function LottieComponent() { return ( <LottieView source={require('./assets/animation.json')} autoPlay loop style={{ width: 200, height: 200 }} /> ); }

Controlling Lottie Animations:

typescript
function ControlledLottie() { const animationRef = useRef<LottieView>(null); const playAnimation = () => { animationRef.current?.play(); }; const pauseAnimation = () => { animationRef.current?.pause(); }; const resetAnimation = () => { animationRef.current?.reset(); }; return ( <View> <LottieView ref={animationRef} source={require('./assets/animation.json')} style={{ width: 200, height: 200 }} /> <Button title="Play" onPress={playAnimation} /> <Button title="Pause" onPress={pauseAnimation} /> <Button title="Reset" onPress={resetAnimation} /> </View> ); }

Common Animation Patterns:

  1. Fade In/Out
typescript
function FadeInOut() { const opacity = useSharedValue(0); const fadeIn = () => { opacity.value = withTiming(1, { duration: 500 }); }; const fadeOut = () => { opacity.value = withTiming(0, { duration: 500 }); }; const style = useAnimatedStyle(() => ({ opacity: opacity.value, })); return ( <Animated.View style={style}> <Button title="Fade In" onPress={fadeIn} /> <Button title="Fade Out" onPress={fadeOut} /> </Animated.View> ); }
  1. Slide Animation
typescript
function SlideAnimation() { const translateX = useSharedValue(-300); const slideIn = () => { translateX.value = withSpring(0); }; const slideOut = () => { translateX.value = withSpring(-300); }; const style = useAnimatedStyle(() => ({ transform: [{ translateX: translateX.value }], })); return ( <Animated.View style={style}> <Text>Slide Content</Text> </Animated.View> ); }
  1. Scale Animation
typescript
function ScaleAnimation() { const scale = useSharedValue(1); const scaleUp = () => { scale.value = withSpring(1.5); }; const scaleDown = () => { scale.value = withSpring(1); }; const style = useAnimatedStyle(() => ({ transform: [{ scale: scale.value }], })); return ( <Animated.View style={style}> <Text>Scale Content</Text> </Animated.View> ); }
  1. Rotate Animation
typescript
function RotateAnimation() { const rotation = useSharedValue(0); const rotate = () => { rotation.value = withTiming(rotation.value + 360, { duration: 1000, easing: Easing.linear, }); }; const style = useAnimatedStyle(() => ({ transform: [{ rotate: `${rotation.value}deg` }], })); return ( <Animated.View style={style}> <Text>Rotate Content</Text> </Animated.View> ); }

Performance Optimization:

  1. Use Native Driver
typescript
// Use useNativeDriver to improve performance Animated.timing(value, { toValue: 1, duration: 500, useNativeDriver: true, // Run on UI thread }).start();
  1. Avoid Complex Layouts in Animations
typescript
// Avoid using flex layout in animated components const style = useAnimatedStyle(() => ({ transform: [{ translateX: translateX.value }], // Avoid using flex-related properties }));
  1. Optimize with shouldComponentUpdate
typescript
const AnimatedComponent = React.memo(({ value }) => { const animatedStyle = useAnimatedStyle(() => ({ opacity: value.value, })); return <Animated.View style={animatedStyle} />; });

Best Practices:

  1. Choose Appropriate Animation Library

    • Simple animations: React Native Animated
    • Complex animations and gestures: React Native Reanimated
    • Designer-created animations: Lottie
  2. Performance First

    • Use native driver
    • Avoid complex layouts in animations
    • Optimize with useMemo and useCallback
  3. User Experience

    • Provide smooth transition effects
    • Avoid over-animating
    • Consider lower-performance devices
  4. Accessibility

    • Provide alternatives for animations
    • Respect user's reduced motion preference
    • Provide animation control options

By using animations appropriately, you can significantly improve user experience and interaction quality of Expo apps.

标签:Expo