Reanimated ve Akışkan 60FPS Animasyonlar
UI/UX standartlarını çok yukarılara çekmek için JS thread dışına çıkarılan ve mikro-animasyonları ku...
Bu makale Mobile alanındaki deneyimlerimi ve yazılım geliştirme metodolojimi aktarmaktadır.
Genel Bakış
UI/UX standartlarını çok yukarılara çekmek için JS thread dışına çıkarılan ve mikro-animasyonları kusursuz yöneten Reanimated 3 implementasyonlarımız.
Profesyonel mobil ürünleri rakiplerinden ayırt eden şey işlevi kadar sunduğu mikro-etkileşimler (Micro-animations) ve pürüzsüz geri bildirim dokularıdır. Ancak React Native JS ipliği animasyonlar için çok yavaştır.
JS Thread vs UI Thread: Neden Animated API Yetmez?
React Native'in yerleşik Animated API'si her frame'de JS thread ile UI thread arasında bridge üzerinden iletişim kurar. Bu köprü geçişi ~5ms gecikme yaratır ve karmaşık animasyonlarda frame drop kaçınılmazdır. Reanimated 3 ise animasyon mantığını tamamen UI thread'ine (native taraf) taşıyarak bu darboğazı ortadan kaldırır.
[Animated API]
JS Thread → Bridge → UI Thread (her frame'de köprü geçişi = jank)
[Reanimated 3]
Worklet → UI Thread (doğrudan native çalışma = 60FPS)
Shared Values ve Worklet'ler
Reanimated'in temel yapı taşı useSharedValue ve useAnimatedStyle hook'larıdır. Shared value'lar UI thread'de yaşar ve JS thread'i bloklamadan animasyonları yönetir.
import Animated, {
useSharedValue,
useAnimatedStyle,
withSpring,
withTiming,
} from 'react-native-reanimated'
function AnimatedCard({ onPress }: Props) {
const scale = useSharedValue(1)
const opacity = useSharedValue(1)
const animatedStyle = useAnimatedStyle(() => ({
transform: [{ scale: scale.value }],
opacity: opacity.value,
}))
const handlePressIn = () => {
scale.value = withSpring(0.95, { damping: 15, stiffness: 150 })
opacity.value = withTiming(0.8, { duration: 100 })
}
const handlePressOut = () => {
scale.value = withSpring(1, { damping: 15, stiffness: 150 })
opacity.value = withTiming(1, { duration: 100 })
}
return (
<Pressable
onPressIn={handlePressIn}
onPressOut={handlePressOut}
onPress={onPress}
>
<Animated.View style={[styles.card, animatedStyle]}>
{/* Card content */}
</Animated.View>
</Pressable>
)
}Gesture Handler Entegrasyonu
react-native-gesture-handler v2 ile Reanimated'i birleştirerek dokunma, sürükleme ve fırlatma hareketlerini 60FPS'de işliyoruz. Swipe-to-delete gibi etkileşimler artık native hissiyatla çalışıyor.
import { Gesture, GestureDetector } from 'react-native-gesture-handler'
import Animated, {
useAnimatedStyle,
useSharedValue,
withSpring,
runOnJS,
} from 'react-native-reanimated'
function SwipeableRow({ onDelete, children }: Props) {
const translateX = useSharedValue(0)
const panGesture = Gesture.Pan()
.onUpdate(event => {
translateX.value = Math.min(0, event.translationX)
})
.onEnd(() => {
if (translateX.value < -120) {
translateX.value = withSpring(-200)
runOnJS(onDelete)()
} else {
translateX.value = withSpring(0)
}
})
const rowStyle = useAnimatedStyle(() => ({
transform: [{ translateX: translateX.value }],
}))
return (
<GestureDetector gesture={panGesture}>
<Animated.View style={rowStyle}>{children}</Animated.View>
</GestureDetector>
)
}Layout Animations: Entering ve Exiting
Reanimated 3'ün layout animation API'si ile liste elemanlarının eklenmesi ve silinmesi sırasında otomatik geçiş animasyonları uyguluyoruz. Tek satır kod ile profesyonel sonuçlar elde ediliyor.
import Animated, {
FadeInDown,
FadeOutLeft,
LinearTransition,
} from 'react-native-reanimated'
function NotificationList({ items }: Props) {
return (
<Animated.FlatList
data={items}
itemLayoutAnimation={LinearTransition}
renderItem={({ item, index }) => (
<Animated.View
entering={FadeInDown.delay(index * 50).springify()}
exiting={FadeOutLeft.duration(300)}
>
<NotificationCard item={item} />
</Animated.View>
)}
/>
)
}Spring vs Timing: Doğru Easing Seçimi
Her animasyon türü için doğru easing fonksiyonu seçmek UX kalitesini belirler. Temel kuralımız: kullanıcı etkileşimi sonucu tetiklenen animasyonlarda spring, otomatik/sistem animasyonlarında timing kullanmak.
| Senaryo | Animasyon Tipi | Neden? |
|---|---|---|
| Buton basma | withSpring | Doğal geri sekme hissi |
| Sayfa geçişi | withTiming + Easing.bezier | Kontrollü ve öngörülebilir |
| Pull-to-refresh | withSpring | Elastik geri dönüş |
| Toast bildirimi | withTiming | Sabit sürede giriş/çıkış |
Kullanıcının tıkladığı nesnenin yumuşakça esnemesi, sayfalar arasındaki sürükleme ivmesinin parmak hızını algılayıp tepki vermesi, UI/UX deneyimi açısından ürünümüzün kalitesini premium segmente yükseltti.
Bu içerik kişisel geliştirme laboratuvarımdan ve prodüksiyon maceralarımdan derlenmiştir.