Animations (Reanimated) — Mobile

Animasi di React Native react-native-reanimated adalah library animasi yang berjalan di UI thread — bukan JS thread. Hasilnya animasi 60fps yang smooth bahkan s

Animasi di React Native

react-native-reanimated adalah library animasi yang berjalan di UI thread — bukan JS thread. Hasilnya animasi 60fps yang smooth bahkan saat JS thread sibuk.

Setup

# Install
npx expo install react-native-reanimated

// babel.config.js — tambahkan plugin
module.exports = function (api) {
  api.cache(true);
  return {
    presets: ['babel-preset-expo'],
    plugins: ['react-native-reanimated/plugin'], // harus terakhir!
  };
};

Basic Animation: useSharedValue + useAnimatedStyle

import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withSpring,
  withTiming,
} from 'react-native-reanimated';

function BouncyBox() {
  const scale = useSharedValue(1);

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [{ scale: scale.value }],
  }));

  const handlePress = () => {
    // Spring animation
    scale.value = withSpring(1.5, {}, () => {
      scale.value = withSpring(1);
    });
  };

  return (
    <Pressable onPress={handlePress}>
      <Animated.View style={[styles.box, animatedStyle]} />
    </Pressable>
  );
}

Entering & Exiting Animations

import Animated, {
  FadeIn,
  FadeOut,
  SlideInRight,
  BounceIn,
} from 'react-native-reanimated';

function AnimatedCard({ visible }) {
  if (!visible) return null;

  return (
    <Animated.View
      entering={SlideInRight.duration(300).springify()}
      exiting={FadeOut.duration(200)}
      style={styles.card}
    >
      <Text>Animated Card</Text>
    </Animated.View>
  );
}

// Layout Animations (auto-animate layout changes)
<Animated.View layout={LinearTransition.springify()}>
  {items.map(item => (
    <Animated.View
      key={item.id}
      entering={FadeIn}
      exiting={FadeOut}
      layout={LinearTransition}
    >
      <Text>{item.name}</Text>
    </Animated.View>
  ))}
</Animated.View>

Gesture Handler + Reanimated

import { Gesture, GestureDetector } from 'react-native-gesture-handler';
import Animated, {
  useSharedValue,
  useAnimatedStyle,
  withDecay,
} from 'react-native-reanimated';

function DraggableBox() {
  const translateX = useSharedValue(0);
  const translateY = useSharedValue(0);

  const pan = Gesture.Pan()
    .onUpdate((e) => {
      translateX.value = e.translationX;
      translateY.value = e.translationY;
    })
    .onEnd((e) => {
      // Momentum/decay setelah release
      translateX.value = withDecay({ velocity: e.velocityX });
      translateY.value = withDecay({ velocity: e.velocityY });
    });

  const animatedStyle = useAnimatedStyle(() => ({
    transform: [
      { translateX: translateX.value },
      { translateY: translateY.value },
    ],
  }));

  return (
    <GestureDetector gesture={pan}>
      <Animated.View style={[styles.box, animatedStyle]} />
    </GestureDetector>
  );
}

Tips Animasi Performant

Yang akan kamu pelajari