Üstel yumuşatma kullanan animasyon hilesi
- Animasyonla ilgili işler yapmaya başladığımdan beri neredeyse her zaman kullandığım basit bir animasyon tekniği var.
- Bu teknik; kamera döndürme ve hareket ettirme, sıra tabanlı oyunlarda karakter hareketi, UI öğelerinin hareketi, ses kütüphanelerinde ses düzeyi değişimlerinin yumuşatılması gibi pek çok yerde kullanılıyor.
- Bu teknik yeni değil; daha önce duymuş veya kullanmış olabilirsiniz, ama birkaç örnek ve matematiksel prensibini açıklayacağım.
Geçiş düğmesi
- UI bileşenleri oluştururken, örneğin bir geçiş düğmesi yaptığınızı varsayalım.
- Geçiş düğmesinin anahtar konumu duruma göre hesaplanır; açıksa
max_x, kapalıysa min_x olarak ayarlanır.
- Bu yaklaşım iyi çalışır, ancak animasyon olmadan biraz cansız görünür.
- Animasyon yalnızca görsel şıklık katmakla kalmaz, kullanıcının ne olduğunu anlamasına da yardımcı olur.
- Geçiş göstergesini anında yeni konuma taşımak yerine, yumuşak biçimde hareket edecek şekilde değiştiririz.
- Artık animasyonu güncellememiz gerekir; bunun dezavantajı sabit hızla hareket ediyormuş gibi görünmesidir.
- Buraya bir easing fonksiyonu ekleyebiliriz; örneğin
3t^2-2t^3 veya sqrt(t) gibi bir fonksiyon kullanılabilir.
- Bu easing fonksiyonları arasındaki farklar, animasyonu yavaş oynattığınızda daha net görülür.
- Artık anahtar konumunu güncellemek yerine animasyon durumunu takip etmek gerekir.
sqrt kullanırken, animasyon yönüne göre farklı easing fonksiyonlarını açıkça kullanmak gerekir.
- Hangisinin daha iyi göründüğü bir zevk meselesi, ama
sqrt en iyi görüneni. Çünkü anahtar çok hızlı başlıyor, ama hedefe yaklaştıkça güzelce yavaşlıyor.
- Bu sürümün dezavantajı, en basit durumda bile hatırı sayılır miktarda yönetim gerektirmesi ve kullanıcı animasyonun ortasında tıklarsa aniden sıçrayan bir süreksizlik oluşmasıdır.
Kamera hareketi
- Harita ve kameranın etrafta kaydırıldığı veya hareket ettirildiği bir durum düşünelim.
- Buraya da animasyon eklemek iyi olur.
- Sabit hızla enterpolasyon yapan kod sunuluyor.
- Animasyon tamamlandıktan sonra oluşan titreme,
target.x - position.x değerinin artı ve eksi arasında gidip gelmesinden kaynaklanır.
sign(delta) yerine deltayı clamp eden bir fonksiyona ihtiyaç vardır.
- Bu yöntem, basit bir şey için oldukça karmaşıktır.
- Animasyon hızı, animasyonun tamamlanmasından daha hızlı olduğunda garip görünür.
- Kullanıcı girdisini animasyon etkinken yok sayabilirsiniz, ama bu kullanıcı için oldukça sinir bozucu bir deneyimdir.
- Mükemmel çözüm ise elbette üstel yumuşatmadır.
- Kod, geçiş düğmesi örneğine kıyasla neredeyse hiç değişmez.
İç işleyiş
1 - exp(- speed * dt) ifadesinin ne olduğu ve nasıl çalıştığı açıklanıyor.
- Daha basit bir sürümle başlayarak, mevcut
position ile gidilmesi gereken yeni konum target arasındaki hızı orantılı hale getirip hareketi hızlandırıyoruz.
- Bu yöntem, mevcut konum ve hedef konum dışında herhangi bir durum tutmayı gerektirmez ve
target aniden değişse bile otomatik olarak uyum sağlar.
- Ancak küçük bir sorun vardır.
speed * dt değeri 1'den büyükse konum hedefi aşar.
- Bu sorunu çözmek için değeri 1'e clamp edebilirsiniz.
speed * dt değerinin fazla büyük olmasının nedeni ya speed değerinin çok büyük olması ya da dt değerinin çok büyük olmasıdır.
- Animasyon açısından,
dt uygulanırken her şeyin her durumda kusursuz çalışması ideal olurdu.
Diferansiyel denklem (ah, hayır)
- Sorunu çözmek için iki aşamalı bir yaklaşım sunuluyor.
position += (target - position) * speed * dt ifadesinin küçük dt için çalışıp büyük dt için başarısız olması, diferansiyel denklemlerin sayısal çözümünde tipik bir problemdir.
- Bu denklemin neyi çözdüğüne bakılıyor.
position += (target - position) * (1 - exp(- speed * dt)) ifadesinin tüm dt değerleri için doğru formül olduğu açıklanıyor.
Hız seçimi
- Animasyonu genelde süre açısından düşünürüz.
- Üstel formül kullanıldığında animasyon teknik olarak sonsuz sürede tamamlanır.
speed parametresinin anlamı şudur: 1 / speed, position değerinin target'a e = 2.71828... kat daha yaklaşması için geçen süredir.
Üstel yumuşatma
- "Üstel yumuşatma" diye arattığınızda tamamen alakasız gibi görünen bir wiki sayfası bulabilirsiniz, ama aslında bu yazıda tartışılanla çok benzer bir formül içerir.
dt değerinin her zaman aynı olduğunu ve target değerinin her yinelemede değiştiğini varsayarsanız, değerleri yineleme numarasına göre indeksleyip position[i] = (target[i] - position[i - 1]) * factor gibi bir şey hesaplayabilirsiniz.
Son paragraf başlığı
- Bu yazı için fikri birkaç aydır taşıyordum ve sonunda tamamlamış olmaktan mutluyum.
- Geliştirme günlüğünü izlediğiniz ve okuduğunuz için teşekkürler.
GN⁺ görüşü
- Bu yazı, animasyonları daha akıcı ve doğal hale getirmek için kullanılan üstel yumuşatma tekniğini açıklıyor. Bu teknik, kullanıcı deneyimini iyileştirmeye ve arayüzün sezgiselliğini artırmaya katkı sağlıyor.
- Üstel yumuşatma, fiziksel hareketi simüle etmede de faydalı olabilir; örneğin oyun geliştirmede karakter hareketini veya kamera geçişlerini daha doğal hale getirmek için kullanılabilir.
- Bu teknik, özellikle kullanıcı arayüzü öğeleri durum değişimi yaşadığında bu değişimi görsel olarak ifade etmede çok etkilidir. Örneğin, slider veya switch hareketlerini daha yumuşak gösterebilir.
- Eleştirel bir açıdan bakıldığında, üstel yumuşatma ile animasyonun hızını ve süresini tam olarak kontrol etmek zor olabilir. Bu da tasarımcıların belirli bir animasyon etkisini hassas biçimde ayarlamak istemesi durumunda bir sınırlama yaratabilir.
- Benzer işlevler sunan diğer animasyon kütüphaneleri veya framework'ler arasında GreenSock Animation Platform(GSAP) ve anime.js sayılabilir; bunlar çeşitli easing fonksiyonlarıyla birlikte daha ince ayarlı animasyon kontrolü sunar.
- Üstel yumuşatma tekniği uygulanırken, animasyonun doğallığı ile kontrol hassasiyeti arasında denge kurmak gerekir. Bu tekniğin avantajı kullanıcı deneyimini iyileştirmesidir; dezavantajı ise animasyon zamanlamasının hassas kontrolünün zor olabilmesidir.
1 yorum
Hacker News görüşleri
İlk yorum özeti:
smoothstep()fonksiyonu değil, çeşitli girdileri tutarlı biçimde işleyen stateless bir yöntem olduğunu vurguluyor.İkinci yorum özeti:
Üçüncü yorum özeti:
sqrt) kübikten (cubic) daha iyi olduğu iddiasına katılmıyor.Dördüncü yorum özeti:
Beşinci yorum özeti:
Altıncı yorum özeti:
Yedinci yorum özeti:
Sekizinci yorum özeti:
Dokuzuncu yorum özeti:
Onuncu yorum özeti: