Merhaba, react native üzerinde animasyonların kullanımlarından bahsedeceğim. Tamamı olmasada bu makaleden alıntı yapılmıştır. (Birebir aynı değildir) Nader Dabit'e teşekkür ederim.
React native içinde animasyon kullanmak için tavsiye edilen yol Animated özelliğini kullanmaktır.
Animated ile animasyon oluşturmak için kullanılan üç adet method :
Biz çoğunlukla Animated.timing() ve Animated.spring() kullanımından bahsedeceğiz.
Bu üç method ile birlikle bazı animasyonlar oluşturmak için üç yöntem daha var :
Oluşturduğumuz ilk animasyon Animated.timing() kullanarak döndürme işlemi olacak:
Animated.timing(
birDeger,
{
toValue: gidecegiDeger,
duration: sure,
easing: easingFunction,
delay: gecikme
}
)
Bu tür sonsuz animasyon, yükleniyor pencereleri oluştururken kullanışlı olabilir. Bu kavram yukarı aşağı boyutlandırma veya başka türde sonsuzluk içeren animasyonlar oluşturmak için kullanılabilir.
Başlamak için, var olan bir react native projesine veya yeni bir react native projesine ihtiyacımız var. react-native init
ile projenizin ismini yazarak projeyi oluşturun, sonra çalışmak için cd ile dizine geçin.
react-native init animasyonlar
cd animasyonlar
Şimdi bu klasördeyiz ve index.android.js
veya index.ios.js
dosyalarını açın.
Şimdi projeyi oluşturduk, ilk yapmamız gereken Animated, Image ve Easing modüllerini import etmek.
import {
...
Animated,
Image,
Easing
} from 'react-native'
Animated, animasyonları oluşturmamız için kullanacağımız kütüphanedir ve React Native ile birlikte gelir.
Kullanıcı Arayüzünde bir resim oluşturmamız için Image kütüphanesi gerekli.
Easing React Native ile gelen bir modüldür. Hazırda bulunan tanımlı linear, ease, quad, cubic, sin, elastic, bounce, back, bezier, in, out, inout ve diğer methodları var. Tutarlı bir doğrusal hareket için linear kullanacağız. Bu anlatılan bölüm bittiğinde nasıl uygulayacağınız konusunda daha iyi bir fikre sahip olacaksınız.
Sonra, döndürme değerimiz için başlangıçta bir animasyon değeri belirlememiz gerekiyor. Bunu yapmak için constructor’ı kullanacağız.
constructor () {
super()
this.donusDegeri = new Animated.Value(0)
}
donusDegeri değerine yeni bir Animated.Value tanımlıyoruz ve başlangıç için 0 (sıfır) veriyoruz
Sonra dondur adında bir method oluşturuyoruz ve bunu view yüklendiğinde yani componentDidMount() olduğunda çalıştırıyoruz.
componentDidMount () {
this.dondur()
}
dondur () {
this.donusDegeri.setValue(0)
Animated.timing(
this.donusDegeri,
{
toValue: 1,
duration: 4000,
easing: Easing.linear
}
).start(() => this.dondur())
}
dondur() - Bu method şunları yapar:
{finished: true}
değerini döner, fakat eğer animasyon başka bir animasyon tarafından kesilmişse {finished: false}
döner. Animasyonumuz sonsuza kadar çalışacak.Animasyon için yapmamız gerekenler bu kadardı, şimdi onu UI üzerinde görelim. render methodunu güncelliyoruz.
render() {
const don = this.donusDegeri.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '360deg']
});
return (
<Animated.Image
style={{
width: 323,
height: 170,
transform: [{rotate: don}]
}}
source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}
/>
)
}
const don
değerine 0deg ile 360deg arasında bir geçiş attık. interpolate() methodu inputRange’e girilen değerleri outputRange’e uygun olarak değiştirir ve yeni bir geçiş oluşturur. Yani 0-1 (veya 0-100 değiştirilebilir) arasındaki değerler interpolate sayesinde 0deg ile 360deg arasına çevrilir. (Aynı işlemleri renkler içinde yapabilirsiniz)
transform: [{rotate: don}]
Her şey tamamsa örnek çalışıyor! Örnek
Easing’in kaynak kodlarına bakarak biraz inceleme yapabilirsiniz. @dabit’in yaptığı örneğe bakarak (biraz türkçeleştirdim) anlayabilirsiniz.
Bu bölümde basitçe Animated.timing() animasyonlarından ve Animated.timing() ile birlikte interpolate kullanımından söz edeceğiz.
Şimdi de this.animasyonDegeri adındaki değişkenle ve bu değer ile birlikte interpolate() ile çoklu animasyonlar oluşturacağız. Şu stilleri kullanacağız:
Tüm kodları temizleyin veya yeni brach’e geçiş yapın
Şimdide constructor’da yeni animasyon değerini atmamız gerekiyor.
constructor () {
super()
this.animasyonDegeri = new Animated.Value(0)
}
Ardından oynat methodunu oluşturduk ve onu componentDidMount() olunca çalıştırdık
componentWillMount() {
this.oynat()
}
oynat() {
this.animasyonDegeri.setValue(0)
Animated.timing(
this.animasyonDegeri,
{
toValue: 1,
duration: 2000,
easing: Easing.linear
}
).start(() => this.oynat())
}
render methodunda ise 5 tane farklı interpolate oluşturduk
render() {
const marginLeft = this.animasyonDegeri.interpolate({
inputRange: [0, 1],
outputRange: [0, 300]
})
const opacity = this.animasyonDegeri.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0, 1, 0]
})
const movingMargin = this.animasyonDegeri.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [0, 300, 0]
})
const textSize = this.animasyonDegeri.interpolate({
inputRange: [0, 0.5, 1],
outputRange: [18, 32, 18]
})
const rotateX = this.animasyonDegeri.interpolate({
inputRange: [0, 0.5, 1],
outputRange: ['0deg', '180deg', '0deg']
})
...
}
interpolate methodu tek bir this.animasyonDegeri ile çok yönlü animasyonlar yapmamızı sağlayan etkili bir methoddur.
Sonra bu oluşan değerleri Animated.View ve Animated.Text component’leri üzerinde deneyelim.
return (
<View style={{flex: 1, marginTop: 100}}>
<Animated.View
style={{
marginLeft,
height: 30,
width: 40,
backgroundColor: 'red'}} />
<Animated.View
style={{
opacity,
marginTop: 10,
height: 30,
width: 40,
backgroundColor: 'blue'}} />
<Animated.View
style={{
marginLeft: movingMargin,
marginTop: 10,
height: 30,
width: 40,
backgroundColor: 'orange'}} />
<Animated.Text
style={{
fontSize: textSize,
marginTop: 10,
color: 'green'}} >
Animasyonlu yazı
</Animated.Text>
<Animated.View
style={{
transform: [{rotateX}],
marginTop: 50,
height: 30,
width: 40,
backgroundColor: 'black'}}>
<Text style={{color: 'white'}}>Bu TransformX kullanıyor</Text>
</Animated.View>
</View>
)
Her şey tamamsa örnek çalışıyor! Örnek
Şimdi ise animasyonumuzu Animated.spring() kullanarak oluşturalım.
// Örnek kullanım
Animated.spring(
animasyonDegeri,
{
toValue: numara,
friction: numara
}
)
Aynı projeden devam edebiliriz. Sadece birkaç yeri güncellemeliyiz. constructor’da animasyonDegeri yerine springDegeri diye tanımlayalım ve 0.3 verelim.
constructor () {
super()
this.springDegeri = new Animated.Value(0.3)
}
oynat methodu yerine springOynat yapalım ve onuda componentDidMount() olduğunda çalıştıralım.
springOynat () {
this.springDegeri.setValue(0.3)
Animated.spring(
this.springDegeri,
{
toValue: 1,
friction: 1
}
).start()
}
Animasyonu bittiğine göre, view üzerinden tıklayarak event tetiklesin bunuda eskiden yaptığımız react native logosuna yapalım:
<Text
style={{marginBottom: 100}}
onPress={this.springOynat.bind(this)}>Spring Yap</Text>
<Animated.Image
style={{ width: 227, height: 200, transform: [{scale: this.springDegeri}] }}
source={{uri: 'https://facebook.github.io/react/img/logo_og.png'}}/>
Her şey tamamsa örnek çalışıyor! Örnek
Animated.parallel() başlarken aynı zamanda bir dizideki animasyonları başlatır.
// API
Animated.parallel(birDiziAnimasyon)
// Kullanımı:
Animated.parallel([
Animated.spring(
animasyonDegeri,
{
//config seçenekleri
}
),
Animated.timing(
animasyonDegeri2,
{
//config seçenekleri
}
)
])
Başlamak için constructor’a 3 tane animasyon değeri tanımlayalım.
constructor () {
super()
this.animasyonDegeri1 = new Animated.Value(0)
this.animasyonDegeri2 = new Animated.Value(0)
this.animasyonDegeri3 = new Animated.Value(0)
}
Sonra oynat methodumuzu componendDidMount() olduğunda çağıralım
componentDidMount () {
this.oynat()
}
oynat () {
this.animasyonDegeri1.setValue(0)
this.animasyonDegeri2.setValue(0)
this.animasyonDegeri3.setValue(0)
const animasyonYap = function (value, duration, easing, delay = 0) {
return Animated.timing(
value,
{
toValue: 1,
duration,
easing,
delay
}
)
}
Animated.parallel([
animasyonYap(this.animasyonDegeri1, 2000, Easing.ease),
animasyonYap(this.animasyonDegeri2, 1000, Easing.ease, 1000),
animasyonYap(this.animasyonDegeri3, 1000, Easing.ease, 2000)
]).start()
}
oynat methodunda üç animasyonun değerini sıfıra çevirdi. Animasyonları oluşturmak için animasyonYap() methoduyla animasyon değeri, duration, easing ve delay argümanlarını kullandık. delay gelmemişse onu sıfıra ayarladık
render methodunda sonraki animasyonlara interpolate ile değer atmamız gerekiyor.
render() {
const scaleText = this.animasyonDegeri1.interpolate({
inputRange: [0, 1],
outputRange: [0.5, 2]
})
const spinText = this.animasyonDegeri2.interpolate({
inputRange: [0, 1],
outputRange: ['0deg', '720deg']
})
const introButton = this.animasyonDegeri3.interpolate({
inputRange: [0, 1],
outputRange: [-100, 400]
})
...
}
Şimdi bunları Animated.Views ile UI üzerinde görelim
return (
<View style={{flex: 1, marginTop: 100, alignItems: 'center'}}>
<Animated.View
style={{ transform: [{scale: scaleText}] }}>
<Text>Hoş Geldiniz Dostlarım!</Text>
</Animated.View>
<Animated.View
style={{ marginTop: 20, transform: [{rotate: spinText}] }}>
<Text
style={{fontSize: 20}}>
Uygulama İçin Dönsün Bu TEXT!
</Text>
</Animated.View>
<Animated.View
style={{top: introButton, position: 'absolute'}}>
<TouchableHighlight
onPress={this.oynat.bind(this)}
style={{
padding: 10,
backgroundColor: 'blue'
}}>
<Text
style={{color: 'white', fontSize: 20}}>
Buraya tıkla ve Başlat
</Text>
</TouchableHighlight>
</Animated.View>
</View>
)
scaleText ilk view, spinText ikinci view ve introButton da üçüncü view. oynat() çalıştırıldığında tüm animasyonlar paralel olarak çalışır.
Her şey tamamsa örnek çalışıyor! Örnek
Şimdi api’ye bir göz atalım ve bu animasyonun nasıl yapıldığına bakalım
// API
Animated.sequence(birDiziAnimasyon)
// Kullanımı
Animated.sequence([
Animated.timing(
animasyonDegeri,
{
//config seçenekleri
}
),
Animated.spring(
animasyonDegeri2,
{
//config seçenekleri
}
)
])
Animated.sequence() de Animated.parallel() gibi bir dizi animasyon alır. Animated.sequence() dizideki animasyonların her birinin tamamlanmasını bekler ve sonraki animasyona geçer, yani sırayla çalışır.
Temel olarak Animated.parallel()'e benzediği için önceki yaptığımız animasyonları tekrarlamıyoruz.
Örnekte dikkat edilmesi gereken nokta, orada animasyon değerlerini bir dizi içine atmış olmamız.
Her şey tamamsa örnek çalışıyor! Örnek ^(yukarıda var)
Şimdi api’ye bir göz atalım ve bu animasyonun nasıl yapıldığına bakalım
// API
Animated.stagger(delay, birDiziAnimasyon)
// Kullanımı
Animated.stagger(1000, [
Animated.timing(
animasyonDegeri,
{
//config seçenekleri
}
),
Animated.spring(
animasyonDegeri2,
{
//config seçenekleri
}
)
])
Animated.parallel() ve Animated.sequence() gibi Animated.Stagger da bir dizi animasyon alır, fakat bu animasyonlar ardışık gecikmelerle sırayla başlatılır.
Örnekte dikkat edilmesi gereken nokta Animated.stagger()'ın ilk parametresi delay(gecikme) içeriyor.
Her şey tamamsa örnek çalışıyor Örnek ^(yukarıda var)
Bütün projenin hepsini bu adreste bulabilirsiniz.
Bu makaleden alıntı yapılmıştır. (Birebir aynı değildir)
Bugün anlatacaklarım bu kadardı aklınıza takılan bir soru olursa çekinmeyin. Eğer bu konu hakkında veya konu dışı olarak bana soru sormak istiyorsanız https://github.com/abdurrahmanekr/bana-istedigini-sor repository’sinde bir issue açabilirsiniz. Youtube kanalıma abone olarak ve yayınladığım bu makaleyi paylaşarak bana destek olabilirsiniz. Diğer makalelerde görüşmek üzere :)
Düşündüklerin nedir ?