Yazılım Mimarileri ve Tasarım Desenleri Üzerine

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;

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;

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.

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.

Ö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.

Ö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;
  }
}

Ö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;

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.

Mobil sürümden çık