Angular 6/7 – Animasyon İşlemleri

Merhaba,

Bu içeriğimizde, Angular mimarisi eşliğinde yapılmış bir uygulamayı görsel olarak süsleyebilmemiz için geliştirilmiş animasyon yapılanmasını inceleyecek, nesnesel animasyonlarla ve componentler arası geçiş efektleriyle konumuzu örneklendirerek adım adım derinlemesine irdeleyeceğiz.

Giriş

Öncelikle “animasyon” kelimesinin fiili boyutunu izah ederek konumuza başlayalım. Animasyon; bir nesnenin/yapının ilk durumdaki halinden son durumdaki haline geçiş süreci olarak ifade edebiliriz. Bu süreçteki etkileşim insanın gözüne hoş bir görüntü vermekle birlikte zihninde ilgi çekici bir izlenim bırakmakta ve o anki ilgilenilen olgu her ne ise eğlenceli hale getirmektedir.

Animasyonlar, günümüz modern web uygulamalarının ayrılmaz birer parçaları olmuşlardır. Son kullanıcının yapmış olduğu bir etkileşim neticesinde uygulama reaksiyona animasyonlar eşliğinde girdiği taktirde ilgili kullanıcının hem uygulamaya olan sempatisini arttıracaktır hem de yapısal olarak uygulamanın kalitesini ortaya koyacaktır.

Başlarken

Bu içeriğimizde Angular uygulamalarında animasyon çalışmalarının nasıl yapıldığını inceleyeceğimizden dolayı pratik ağırlıklı bir seyir halinde olacağız. Dolayısıyla makaleye eşlik edebilmeniz için hazırbulunuşluluk açısından ilk olarak içerisinde aşağıdaki yapıları ve configürasyonu barındıran boş bir Angular projesi oluşturunuz;

  • “Home”, “About” ve “Contact” isimlerinde üç adet component oluşturunuz,
  • @angular/platform-browser/animations kütüphanesindeki BrowserAnimationsModule modülünü uygulamanın ana modülüne import ediniz;
    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppRoutingModule } from './app-routing.module';
    import { AppComponent } from './app.component';
    import { HomeComponent } from './home/home.component';
    import { AboutComponent } from './about/about.component';
    import { ContactComponent } from './contact/contact.component';
    import { BrowserAnimationsModule } from "@angular/platform-browser/animations";
    @NgModule({
      declarations: [
        AppComponent,
        HomeComponent,
        AboutComponent,
        ContactComponent
      ],
      imports: [
        BrowserModule,
        AppRoutingModule,
        BrowserAnimationsModule
      ],
      providers: [],
      bootstrap: [AppComponent]
    })
    export class AppModule { }
    

Evet… Artık hazırız…

Animasyon Geçiş Zamanlaması

Yukarıdaki satırlarda “Giriş” paragrafında Animasyon fiiliyatının izahatini yapmış ve “bir nesnenin/yapının ilk durumdaki halinden son durumdaki haline geçiş süreci olarak ifade edebiliriz” şeklinde tanımlamıştık.

İşte bu -ilk halden- -son hale- geçiş sürecinde animasyon geçiş zamanlaması temel konfigürasyonu sağlamaktatır. Angular animasyon geçişi için aşağıdaki üç farklı zamanlama özelliğini sunmaktadır;

  1. Duration(Süre)
    Bu özellik, animasyonun -ilk halden- -son hale- kadar geleceği zamanı ifade eder. Aşağıdaki gibi üç farklı yolla tanımlayabiliriz;

    • Milisaniye cinsinden süreyi temsil eden bir tamsayı değeri kullanma. Örneğin; 500
    • Milisaniye cinsinden süreyi temsil etmek için bir dize değeri kullanma. Örneğin; ‘500ms’
    • Süreyi saniye cinsinden göstermek için bir dize değeri kullanma. Örneğin; ‘0.5s’
  2. Delay(Gecikme)
    Bu özellik, tetiklenen animasyon anı ile gerçek geçişin başlaması arasındaki süreyi temsil eder. Aşağıdaki gibi tanımlanabilir;

    • ‘0.3s 500ms’ : Bu ifade, animasyon tetiklendiği andan itibaren 500 milisaniye bekleyeceği ve daha sonra gerçek geçişin başlamasıyla birlikte animasyonun 0.3 saniye süreceği anlamına gelir.
    • ’10s 3000ms’ : Animasyon 3000 milisaniye bekleyecek, ardından 10 saniye geçiş sürecektir.
  3. Easing(Hareket Hızı)
    Bu özellik ise animasyonun gerçekleşmesi esnasında nasıl hızlanıp yavaşlayacağını ifade eder.
    Aşağıdaki gibi tanımlanabilir;

    • ‘0.3s 500ms ease-in’
    • ‘0.3s 3000ms ease-out’

Temel Animasyon Fonksiyonları

Bir nesneye yahut componentler arası geçişe animasyon uygulayabilmek için @angular/animations modülü altındaki fonksiyonları kullanmaktayız. Şimdi gelin teorik olarak bu fonksiyonları inceleyelim;

  • trigger
    Uygulama için tasarlanmış tüm animasyonlar esasında birer etikete sahiptirler. Çalışma zamanında hangi animasyon tetikleniyorsa ilgili animasyona özel bir trigger fırlatılmakta ve süreç başlatılmaktadır.

    Örnek 1.0;
    “MesajGoster” animasyonu başlatıldı

  • state
    Animasyonun alacağı aksiyonun değerini kontrol eden fonksiyondur.
    Örnek 1.1;
    State değerleri “aç”/”kapat”
  • style
    state fonksiyonu sayesinde yakalanan değerler eşliğinde, hangi değerde hangi stillerin uygulanacağını vs. yani tüm transform ayarlarını style fonksiyonu sayesinde belirtmekteyiz.
    Örnek 1.2;
    “aç” isimli state değerinin style yapılanması şöyle;

    • Arkaplan rengi mavi
    • Yazılar turuncu
    • Yazı boyutları 17px vs.

    “kapat” isimli state değerinin style yapılanması ise şöyle;

    • Arkaplan rengi kahverengi
    • Yazılar gri
    • Yazı boyutları 13px vs.

  • transition
    state değerlerine özel tanımlanmış style’lar arasında geçişi sağlamak için kullanılan fonksiyondur.
    Örnek 1.3;
    Gelen state değeri “aç” ise; “kapat => aç” değil ise “aç => kapat” olacak şekilde geçiş yap.
  • animate
    transition fonksiyonuyla yapılacak olan geçişin belirtilen geçiş zamanlaması zarfında gerçekleşmesini sağlayan fonksiyondur. Yani animasyon harekatını başlatan fonksiyondur.
    Örnek 1.4;
    Animasyonu 1500 milisaniye içerisinde gerçekleştir.
  • query
    Componentler arası geçiş animasyonlarında componente giriş yahut çıkış durumlarında beklenen style yapılandırmasını sağlamak için kullanılan fonksiyondur. transition fonksiyonu içerisinde parametre olarak kullanılır.
  • group
    İçerisinde birden fazla query olacak olan transition fonksiyonunda bu queryleri group fonksiyonu aracılığıyla tek bir dizi şeklinde tanımlayıp, tutabiliriz.

Animasyon Oluşturma

Oluşturulan animasyonlar ilgili componentin “@Component” deklarasyonu içerisindeki “animations” dizisinde trigger fonksiyonları olarak tutulacaktır. Tabi bunun için öncelikle animasyon uygulanacak yapıya yahut nesneye aşağıdaki gibi bir etiket tanımlaması yapmamız gerekmektedir.
Angular 7 - Animasyon İşlemleri
Animasyon tetiklendiği vakit, tanımlanan bu etiket adına uygun trigger devreye girecek ve varsa tanımlanmış olan değişken değerini state olarak bizlere iletecektir.

Şimdi bunu bir kaç örnekle inceleyeceğiz. İçeriğimizde pratiksel anlatım sergileyebilmek için yapacağımız nesnesel animasyon örneklendirmeleri önceden oluşturduğumuz(‘başlarken’ başlığı altında değinmiştim) “HomeComponent” altında gerçekleştireceğiz. Bunun haricinde componentler arası animasyonel geçişlerde ise örneklendirmek maksadıyla mevcutta bulunan tüm componentleri kullanacağız.

Örnek 1

Bu örneğimizde bir div nesnesinin boyutunu animasyonel olarak değiştireceğiz.

<button type="button" class="btn btn-primary" (click)="boyutDegistir()">Boyut Değiştir</button>
<div [@boyut]="boyutDurumu"></div>
import { Component } from '@angular/core';
import { trigger, state, style, transition, animate } from "@angular/animations";

@Component({
  templateUrl: './home.component.html',
  animations: [
    trigger("boyut", [
      state("0", style({
        backgroundColor: "yellow",
        width: "100px",
        height: "100px"
      })),
      state("1", style({
        backgroundColor: "green",
        width: "300px",
        height: "300px"
      })),
      transition("0 => 1", animate("500ms")),
      transition("1 => 0", animate("500ms")),
    ])
  ]
})
export class HomeComponent {
  boyutDurumu = 0;
  boyutDegistir() {
    this.boyutDurumu = this.boyutDurumu === 0 ? 1 : 0;
  }
}

Yukarıdaki yapılanmayı incelerseniz eğer “@boyut” etiketine sahip olan div nesnesi “boyutDurumu” isimli değer üzerinden animasyonel bir aksiyon gerçekleştirmektedir. Butona tıklandığı vakit “boyutDegistir” isimli fonksiyon tetiklenecektir ve içerisinde “boyutDurumu” isimli değişkenin değeri değiştirilecektir. İşte bu durumda “boyutDurumu” değeri değiştiğinden dolayı “@boyut” etiketine sahip olan trigger devreye girecek ve state değerine göre gerekli transition işlemini “500ms” içerisinde gerçekleştirecektir.

Angular 7 - Animasyon İşlemleri

Örnek 2

Bu örnekte ise bir veri kümesine animasyonel bir şekilde veri ekleyip, sileceğiz.

<button type="button" class="btn btn-primary" (click)="elemanEkle()">Eleman Ekle</button><button type="button"
  class="btn btn-danger m-1" (click)="elemanSil()">Eleman Sil</button>

<ul>
  <li [@elemanEkle] *ngFor="let eleman of elemanListesi">Eleman {{eleman}}</li>
</ul>
import { Component } from '@angular/core';
import { trigger, state, style, transition, animate } from "@angular/animations";

@Component({
  templateUrl: './home.component.html',
  animations: [
    trigger("elemanEkle", [
      state("void", style({
        opacity: 0
      })),
      transition("void <=> *", animate(1000))
    ])
  ]
})
export class HomeComponent {
  elemanListesi: number[] = [];
  sayac: number = 0;
  elemanEkle() {
    this.elemanListesi.push(++this.sayac);
  }
  elemanSil() {
    this.elemanListesi.length -= 1;
  }
}

Yukarıdaki yapılanmada ise “elemanListesi” isimli veri kaynağına veri eklenmekte ve silinmektedir. Tüm bu işlem gerçekleştirilirken “@elemanEkle” etiket değerine sahip li nesnesi, herhangi bir değişken bağlantısı söz konusu olmadığından dolayı state değeri void olarak tarif edilmektedir ve “void <=> *” komutu eşliğinde animasyonu devreye sokmaktadır.

Burada DOM’un bir parçası olmayan ve çalışma zamanında listeye eklenen öğenin state’ini void ile karşılamaktayız. Bunun nedeni; eğer ki DOM’a yerleştirilmeyen bir öğe oluşturursanız veyahut DOM’da olmayan bir öğeyi kaldırırsanız bu durumun state’i void olarak temsil edilecektir. Dolayısıyla DOM’da olmayan bir öğe eklenirken veya kaldırılırken animasyon oluşturmak için kullandığımız state değerimiz void ile ifade edilir.

Ayriyetten tüm tetiklenme durumlarına istinaden, çift yönlü bir etkileşimin söz konusu olduğu durumlarda “<=>” ifadesini ve bununla birlikte tümünü ifade eden “*” karakterini kullanmaktayız.
Angular 7 - Animasyon İşlemleri

Örnek 3

Yine benzer şekilde veri kümesine farklı tonda animasyonel işlem gerçekleştireceğiz.

<button type="button" class="btn btn-primary" (click)="elemanEkle()">Eleman Ekle</button><button type="button"
  class="btn btn-danger m-1" (click)="elemanSil()">Eleman Sil</button>

<ul>
  <li [@ucarakElemanEkle]="'ucarakEkle'" *ngFor="let eleman of elemanListesi">Eleman {{eleman}}</li>
</ul>
import { Component } from '@angular/core';
import { trigger, state, style, transition, animate } from "@angular/animations";

@Component({
  templateUrl: './home.component.html',
  animations: [
    trigger("ucarakElemanEkle", [
      state("ucarakEkle", style({ transform: "translateX(0)" })),
      transition(":enter", [
        style({ transform: 'translateX(-100%)' }),
        animate("500ms")
      ]),
      transition(':leave', [
        animate(1000, style({ transform: 'translateX(100%)' }))
      ])
    ])
  ]
})
export class HomeComponent {
  elemanListesi: number[] = [];
  sayac: number = 0;
  durum = 0;
  elemanEkle() {
    this.elemanListesi.push(++this.sayac);
  }
  elemanSil() {
    this.elemanListesi.length -= 1;
  }
}

Angular 7 - Animasyon İşlemleri

Örnek 4

Ve son olarak componentler arası geçişler için bir animasyon oluşturalım. Tabi bu işlem diğer örneklerdekine nazaran biraz daha uğraş gerektireceğinden dolayı adım adım ilerleyelim;

  • Adım 1
    İlk olarak componente özel geçiş animasyonu kazandırabilmek için route yapılanmasını aşağıdai gibi inşa etmeliyiz.

    const routes: Routes = [
      { path: "", redirectTo: "/home", pathMatch: "full" },
      { path: "home", component: HomeComponent, data: { animation: "home" } },
      { path: "about", component: AboutComponent, data: { animation: "about" } },
      { path: "contact", component: ContactComponent, data: { animation: "contact" } }
    ];
    
  • Adım 2
    Ardından componentler arası yönlendirme neticesinde ilgili componentin html’inin basıldığı yer olan router-outlet keywordünün üzerinde aşağıdaki gibi işlem yapılması yeterlidir.(router-outlet, örnek projemizde AppComponent içerisinde tanımlanmıştır)

    .
    .
    .
    <div [@routeAnimations]="o && o.activatedRouteData && o.activatedRouteData['animation']">
      <router-outlet #o="outlet"></router-outlet>
    </div>
    .
    .
    .
    
  • Adım 3
    Component bazlı animasyonlarımızı tek tek oluşturmalıyız.

    import { Component } from '@angular/core';
    import { transition, group, style, animate, query, trigger } from '@angular/animations';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.css'],
      animations: [
        trigger('routeAnimations', [
          transition('home => *', [
            query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
            group([
              query(':enter', [
                style({ transform: 'translateX(100%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
              ], { optional: true }),
              query(':leave', [
                style({ transform: 'translateX(0%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))
              ], { optional: true }),
            ])
          ]),
          transition('contact => *', [
            query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
            group([
              query(':enter', [
                style({ transform: 'translateX(-100%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
              ], { optional: true }),
              query(':leave', [
                style({ transform: 'translateX(0%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))
              ], { optional: true }),
            ])
          ]),
          transition('about => contact', [
            query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
            group([
              query(':enter', [
                style({ transform: 'translateX(100%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
              ], { optional: true }),
              query(':leave', [
                style({ transform: 'translateX(0%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(-100%)' }))
              ], { optional: true }),
            ])
          ]),
          transition('about => home', [
            query(':enter, :leave', style({ position: 'fixed', width: '100%' }), { optional: true }),
            group([
              query(':enter', [
                style({ transform: 'translateX(-100%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(0%)' }))
              ], { optional: true }),
              query(':leave', [
                style({ transform: 'translateX(0%)' }),
                animate('0.5s ease-in-out', style({ transform: 'translateX(100%)' }))
              ], { optional: true }),
            ])
          ]),
        ])
      ]
    })
    export class AppComponent { }
    

    Şöyle bi yukarıdaki tüm transition tanımalamalarına göz atarsak eğer sayfa tasarısına uygun bir şekilde animasyon yapılanmasının sağlandığını düşünebilirsiniz. Nihayetinde “Home” | “About” | “Contact” şeklinde bir sıralama ile routeları yerleştirdiğimizi düşünürsek son kullanıcının yapmış olduğu yönlendirme isteklerini bu sıralamaya uygun bir şekilde animasyonel olarak karşılamaktayız.

    10. satırda; “home => *” direktifini belirterek “home” routeundan olacak tüm çıkışları sola kayacak girişleri ise sağa kayacak şekilde, 23. satırda; “contact => *” ifadesi ile “contact” routeundan olacak tüm çıkışları sağa girişleri ise sola kayacak şekilde ve 36 ile 49. satırlarda tanımlanan “about => contact” ve “about => home” ifadeleri ilede “about” routeuna olan tüm girişlerin ve çıkışların yönüne göre ya sağa ya da sola doğru bir geçiş olacak şekilde animasyonlar gerçekleştirilmiştir.

Angular 7 - Animasyon İşlemleri

Bu satırların akabinde artık Angular uygulamalarınızda kaliteli animasyonlar eşliğinde kullanıcılarınızı karşılayabilir ve onlara daha canlı hizmet sağlayabilirsiniz.

Örnek projeyi indirmek için buraya tıklayınız.

İlgilenenlerin faydalanması dileğiyle…
Sonraki yazılarımda görüşmek üzere…
İyi çalışmalar.

Bunlar da hoşunuza gidebilir...

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

*

Copy Protected by Chetan's WP-Copyprotect.