Web Animasyonları API'si ile Karmaşıklığı Düzenleme

Yayınlanan: 2022-03-10
Hızlı özet ↬ Web Animations API'de bu kadar kolay seçilemeyecek kadar çok seçenek var. Zamanlamanın nasıl çalıştığını ve aynı anda birkaç animasyonun oynatılmasını nasıl kontrol edeceğinizi öğrenmek, projelerinizi temel alacak sağlam bir temel oluşturur.

Basit geçişler ve karmaşık animasyonlar arasında orta yol yoktur. Ya CSS Geçişlerinin ve Animasyonlarının sağladığı şeyler konusunda sorun yaşamazsınız ya da birdenbire alabileceğiniz tüm güce ihtiyaç duyarsınız. Web Animasyonları API'si, animasyonlarla çalışmanız için size birçok araç sunar. Ama onlarla nasıl başa çıkacağını bilmelisin. Bu makale, esnek kalırken karmaşık animasyonlarla başa çıkmanıza yardımcı olabilecek ana noktalar ve teknikler konusunda size yol gösterecektir.

Makaleye girmeden önce, Web Animasyonları API'si ve JavaScript'in temellerini bilmeniz çok önemlidir. Açıklığa kavuşturmak ve eldeki sorundan dikkatin dağılmasını önlemek için sağlanan kod örnekleri açıktır. Fonksiyonlardan ve nesnelerden daha karmaşık bir şey olmayacak. Animasyonlara güzel bir giriş noktası olarak, genel bir referans olarak MDN'yi, Daniel C. Wilson'ın mükemmel serisini ve Ollie Williams'ın CSS Animations vs Web Animations API'sini öneririm. Etkileri tanımlamanın ve istediğiniz sonuca ulaşmak için onları ayarlamanın yollarından geçmeyeceğiz. Bu makale, animasyonlarınızı tanımladığınızı ve bunları işlemek için fikir ve tekniklere ihtiyacınız olduğunu varsayar.

Arayüzlere ve bunların ne işe yaradığına genel bir bakışla başlıyoruz. Ardından neyin, ne zaman ve ne kadar süreyle kullanılacağını belirlemek için zamanlamaya ve kontrol seviyelerine bakacağız. Bundan sonra, birkaç animasyonu nesnelere sararak nasıl tek bir animasyon olarak ele alacağımızı öğreneceğiz. Bu, Web Animasyonları API'sini kullanma yolunda iyi bir başlangıç ​​olacaktır.

Arayüzler

Web Animasyonları API'si bize yeni bir kontrol boyutu sağlıyor. Bundan önce, CSS Geçişleri ve Animasyon, efektleri tanımlamanın güçlü bir yolunu sunarken hala tek bir harekete geçirme noktasına sahipti. Bir ışık anahtarı gibi, ya açıktı ya da kapalıydı. Oldukça karmaşık efektler oluşturmak için gecikmeler ve yumuşatma işlevleriyle oynayabilirsiniz. Yine de, belirli bir noktada, hantal ve çalışmak zor hale geliyor.

Web Animations API, bu tek çalıştırma noktasını oynatma üzerinde tam kontrole dönüştürür. Işık anahtarı, kaydırıcılı bir kısma anahtarına dönüşür. İsterseniz, tüm akıllı ev olayına dönüştürebilirsiniz, çünkü oynatma kontrolüne ek olarak, çalışma zamanında efektleri tanımlayabilir ve değiştirebilirsiniz. Artık efektleri bağlama göre uyarlayabilir veya gerçek zamanlı önizlemeli bir animasyon düzenleyici uygulayabilirsiniz.

Animasyon arayüzü ile başlıyoruz. Bir animasyon nesnesi elde etmek için Element.animate yöntemini kullanabiliriz. Ona anahtar kareler ve seçenekler verirsiniz ve animasyonunuzu hemen oynatır. Ayrıca yaptığı şey, bir Animation nesnesi örneği döndürmesidir. Amacı, oynatmayı kontrol etmektir.

Bunları hatırlıyorsanız, bir kaset çalar gibi düşünün. Bazı okuyucuların ne olduğunu bilmediğinin farkındayım. Soyut bilgisayarlı şeyleri tanımlamak için gerçek dünya kavramlarını uygulamaya yönelik herhangi bir girişimin hızla dağılması kaçınılmazdır. Ama size - bir kaseti kurşun kalemle geri sarmanın keyfini bilmeyen bir okuyucuya - kasetçaların ne olduğunu bilen insanların bu makalenin sonunda kafalarının daha da karışacağına dair güvence verin.

Bir kutu hayal edin. Kasetin gittiği bir yuvaya ve oynatma, durdurma ve geri sarma düğmelerine sahiptir. Animasyon arabirimi örneği budur — tanımlı animasyonu tutan ve oynatımıyla etkileşim kurmanın yollarını sağlayan bir kutu . Oynamak için bir şey veriyorsunuz ve size kontrolleri geri veriyor.

Aldığınız kontroller, ses ve video öğelerinden aldığınız kontrollere kolaylıkla benzer. Bunlar oynat ve duraklat yöntemleri ve geçerli zaman özelliğidir. Bu üç kontrolle, oynatma söz konusu olduğunda her şeyi oluşturabilirsiniz.

Kasetin kendisi, canlandırılan öğeye bir referans, efektlerin tanımı ve diğer şeylerin yanı sıra zamanlamayı içeren seçenekler içeren bir pakettir . Ve işte KeyframeEffect budur. Kaset kasetimiz, tüm kayıtları ve kayıtların uzunluğu hakkında bilgileri tutan bir şeydir. Tüm bu özellikleri fiziksel bir kasetin bileşenleriyle eşleştirmeyi daha yaşlı izleyicilerin hayal gücüne bırakacağım. Size göstereceğim şey kodda nasıl göründüğü.

Element.animate aracılığıyla bir animasyon oluşturduğunuzda, üç şey yapan bir kısayol kullanırsınız. Bir KeyframeEffect örneği oluşturur. Yeni bir Animation örneğine girer. Hemen oynamaya başlar.

 const animation = element.animate(keyframes, options);

Onu parçalayalım ve aynı şeyi yapan eşdeğer kodu görelim.

 const animation = new Animation( // (2) new KeyframeEffect(element, keyframes, options) // (1) ); animation.play(); (3)

Kaseti (1) alın, bir oynatıcıya (2) yerleştirin, ardından Oynat düğmesine (3) basın.

Sahne arkasında nasıl çalıştığını bilmenin amacı, ana karelerin tanımını ayırabilmek ve ne zaman oynatılacağına karar vermektir. Koordine edilecek çok sayıda animasyonunuz olduğunda, oynamaya hazır olduklarını bilmeniz için önce hepsini toplamanız yararlı olabilir. Onları anında oluşturmak ve doğru zamanda oynamaya başlayacaklarını ummak, ummak isteyeceğiniz bir şey değildir. İstenilen efekti birkaç kare sürükleyerek kırmak çok kolaydır. Sürükleyen uzun bir dizi durumunda birikir ve sonuçta hiç inandırıcı bir deneyim olmaz.

Atlamadan sonra daha fazlası! Aşağıdan okumaya devam edin ↓

Zamanlama

Komedide olduğu gibi, animasyonlarda da zamanlama her şeydir. Bir efektin işe yaraması için, belirli bir hissi elde etmek için özelliklerin değişme biçimine ince ayar yapabilmeniz gerekir. Web Animations API'de kontrol edebileceğiniz iki zamanlama düzeyi vardır.

Bireysel özellikler düzeyinde, offset var. Offset, size tek özellik zamanlaması üzerinde kontrol sağlar. Ona sıfırdan bire bir değer vererek her efektin ne zaman başlayacağını tanımlarsınız. Atlandığında sıfıra eşittir.

@keyframes / from yerine yüzdeleri to kullanabileceğinizi hatırlayabilirsiniz. offset yüze bölünmesiyle elde edilen şey budur. offset değeri, tek bir yineleme süresinin bir kısmıdır .

offset , ana kareleri bir KeyframeEffect içinde düzenlemenize olanak tanır. Göreceli bir sayı ofseti olmak, oynatma süresi veya hızı ne olursa olsun, tüm ana karelerinizin birbirine göre aynı anda başlamasını sağlar.

Daha önce de belirttiğimiz gibi, offset , sürenin bir parçasıdır . Şimdi bu konudaki hatalarımdan ve zaman kaybımdan kaçınmanızı istiyorum. Animasyon süresinin, bir animasyonun genel süresiyle aynı şey olmadığını anlamak önemlidir. Genellikle aynıdırlar ve kafanızı karıştırabilecek olan da budur ve kesinlikle kafamı karıştıran da budur.

Süre , bir yinelemenin tamamlanması için geçen milisaniye cinsinden süredir . Varsayılan olarak toplam süreye eşit olacaktır. Bir animasyon süresinde bir gecikme eklediğinizde veya yineleme sayısını artırdığınızda, size bilmek istediğiniz sayıyı söylemeyi bırakır. Bunu kendi yararınıza kullanmayı anlamak önemlidir.

Medya oynatma gibi daha büyük bir bağlamda bir ana kare oynatmayı koordine etmeniz gerektiğinde, zamanlama seçeneklerini kullanmanız gerekir. Aşağıdaki denklemde animasyonun başından "bitmiş" olaya kadar olan tüm süresi:

 delay + (iterations × duration) + end delay

Aşağıdaki demoda çalışırken görebilirsiniz:

Kirill Myshkin'in kaleminden [Bir animasyonun gerçek süresi nedir?](https://codepen.io/smashingmag/pen/VwWWrzz) konusuna bakın.

Kaleme Bakın Bir animasyonun gerçek süresi nedir? Kirill Myshkin'in fotoğrafı.

Bunun yapmamıza izin verdiği şey, birkaç animasyonu sabit uzunluklu medya bağlamında hizalamaktır . İstenen animasyon süresini olduğu gibi koruyarak, daha uzun süreli bir bağlama gömmek için başlangıçta gecikme ve sonunda delay Sonu ile " delayEnd ". Bunu düşünürseniz, delay bu anlamda ana karelerde ofset gibi davranır. Gecikmenin milisaniye cinsinden ayarlandığını unutmayın, bu nedenle onu göreceli bir değere dönüştürmek isteyebilirsiniz.

Animasyonu hizalamaya yardımcı olacak bir diğer zamanlama seçeneği iterationStart . Bir yinelemenin başlangıç ​​konumunu ayarlar. Bilardo topu demosuna katılın. iterationStart Başlat kaydırıcısını ayarlayarak topun başlangıç ​​konumunu ve dönüşünü ayarlayabilirsiniz, örneğin ekranın ortasından atlamaya başlayacak şekilde ayarlayabilir ve son karede kameradaki sayının düz olmasını sağlayabilirsiniz.

Kirill Myshkin'in kaleminden [Tweak interationStart](https://codepen.io/smashingmag/pen/qBjjVPR) konusuna bakın.

Kirill Myshkin'in kaleme aldığı Pen Tweak etkileşimine bakın.

Birkaçını Bir Olarak Kontrol Edin

Bir sunum uygulaması için animasyon düzenleyici üzerinde çalışırken, bir zaman çizelgesindeki tek bir öğe için birkaç animasyon düzenlemem gerekiyordu. İlk denemem, animasyonumu bir zaman çizelgesinde doğru başlangıç ​​noktasına koymak için offset kullanmaktı.

Bunun offset kullanmanın yanlış yolu olduğu çabucak kanıtlandı. Bu özel kullanıcı arayüzü açısından, zaman çizelgesindeki hareketli animasyon, animasyonun süresini değiştirmeden başlangıç ​​konumunu değiştirmek anlamına geliyordu. offset ile bu, sürenin değişmediğinden emin olmak için birkaç şeyi, offset kendisini ve ayrıca kapanış özelliğinin offset değiştirmem gerektiği anlamına geliyordu. Çözümün kavranamayacak kadar karmaşık olduğu ortaya çıktı.

İkinci sorun transform özelliği ile geldi. Bir öğede çeşitli karakteristik değişiklikleri temsil edebilmesi nedeniyle, istediğiniz şeyi yapmasını sağlamak zor olabilir. Bu özellikleri birbirinden bağımsız olarak değiştirmek istendiğinde daha da zorlaşabilir. Ölçek fonksiyonunun değişimi, onu takip eden tüm fonksiyonları etkiler. İşte bu yüzden oluyor.

Transform özelliği, bir dizide bir değer olarak birkaç işlevi alabilir . İşlev sırasına bağlı olarak sonuç değişir. scale alın ve translate edin. Bazen translate bir öğenin boyutuna göre yüzde olarak tanımlamak kullanışlıdır. Diyelim ki bir topun tam olarak üç kendi çapı kadar yükseğe zıplamasını istiyorsunuz. Şimdi, ölçek işlevini nereye yerleştirdiğinize bağlı olarak - translate önce veya sonra - sonuç, orijinal boyutun veya ölçeklenmiş olanın üç yüksekliğinden değişir.

transform özelliğinin önemli bir özelliğidir. Oldukça karmaşık bir dönüşüm elde etmek için buna ihtiyacınız var. Ancak bu dönüşümlerin farklı ve bir öğenin diğer dönüşümlerinden bağımsız olmasına ihtiyaç duyduğunuzda, yolunuza çıkar.

Tüm efektleri tek bir transform özelliğine koyamayacağınız durumlar vardır. Çok hızlı bir şekilde çok fazla olabilir. Özellikle ana kareleriniz farklı yerlerden geliyorsa , dönüştürülmüş bir dizenin çok karmaşık bir birleşimine ihtiyacınız olacaktır. Mantık basit olmadığı için otomatik bir mekanizmaya pek güvenemezsiniz. Ayrıca, ne bekleyeceğinizi anlamak zorlaşabilir. Bunu basitleştirmek ve esnekliği korumak için bunları farklı kanallara ayırmamız gerekiyor.

Bir çözüm, öğelerimizi, her biri ayrı ayrı canlandırılabilen div s'ye sarmaktır ; örneğin, tuval üzerine konumlandırmak için bir div, ölçekleme için bir diğeri ve döndürme için üçüncü bir div. Bu şekilde, yalnızca animasyonların tanımını büyük ölçüde basitleştirmekle kalmaz, aynı zamanda uygun olduğunda farklı dönüşüm kökenleri tanımlama olasılığını da açarsınız.

Bu numarayla işler kontrolden çıkmış gibi görünebilir. Daha önce yaşadığımız sorunların sayısını çarpıyoruz. Aslında, bu numarayı ilk bulduğumda çok fazla olduğu için attım. transform özelliğimin tüm parçalardan tek parça halinde doğru sırayla derlendiğinden emin olabileceğimi düşündüm. İşleri yönetmek için çok karmaşık ve bazı şeyleri imkansız kılmak için bir transform işlevi daha aldı. transform özelliği dize derleyicimin doğru olması gittikçe daha fazla zaman almaya başladı, bu yüzden pes ettim.

Birkaç animasyonun oynatılmasını kontrol etmenin başlangıçta göründüğü kadar zor olmadığı ortaya çıktı. En başından beri kaset çalar benzetmesini hatırlıyor musunuz? Herhangi bir sayıda kaset alan kendi oynatıcınızı kullanabilseydiniz ne olurdu? Dahası, o oynatıcıya istediğiniz kadar düğme ekleyebilirsiniz.

Tek bir animasyonda play çağırmak ile bir dizi animasyonu çağırmak arasındaki tek fark, yinelemeniz gerekmesidir. Herhangi bir Animation örneği yöntemi için kullanabileceğiniz kod:

 // To play just call play on all of them animations.forEach((animation) => animation.play());

Bunu, oynatıcımız için her türlü işlevi oluşturmak için kullanacağız.

Animasyonları tutacak ve oynatacak o kutuyu oluşturalım. Bu kutuları uygun olan herhangi bir şekilde oluşturabilirsiniz. Açıklığa kavuşturmak için, size bunu bir fonksiyon ve bir nesne ile yapmanın bir örneğini göstereceğim. createPlayer işlevi, senkronize olarak oynatılacak bir dizi animasyonu alır. Tek bir play yöntemiyle bir nesne döndürür.

 function createPlayer(animations) { return Object.freeze({ play: function () { animations.forEach((animation) => animation.play()); } }); }

İşlevselliği genişletmeye başlamak için bilmeniz yeterlidir. Duraklatma ve currentTime yöntemlerini ekleyelim.

 function createPlayer(animations) { return Object.freeze({ play: function () { animations.forEach((animation) => animation.play()); }, pause: function () { animations.forEach((animation) => animation.pause()); }, currentTime: function (time = 0) { animations.forEach((animation) => animation.currentTime = time); } }); }

Bu üç yöntemle createPlayer , istediğiniz sayıda animasyonu düzenlemek için size yeterli kontrol sağlar . Ama hadi biraz daha ileri itelim. Oyuncumuzun sadece herhangi bir sayıda kaseti değil, diğer oyuncuları da alabilmesi için yapalım.

Daha önce gördüğümüz gibi, Animation arayüzü medya arayüzlerine benzer. Bu benzerliği kullanarak oynatıcınıza her türlü şeyi koyabilirsiniz. Buna uyum sağlamak için, hem animasyon nesneleri hem de createPlayer gelen nesnelerle çalışmasını sağlamak için currentTime yöntemini ince ayar yapalım.

 function currentTime(time = 0) { animations.forEach(function (animation) { if (typeof animation.currentTime === "function") { animation.currentTime(time); } else { animation.currentTime = time; } }); }

Az önce oluşturduğumuz oynatıcı, tek elemanlı animasyon kanalları için birkaç div karmaşıklığını gizlemenize izin verecek olan şeydir. Bu unsurlar bir sahnede gruplandırılabilir. Ve her sahne daha büyük bir şeyin parçası olabilir. Bu teknikle her şey yapılabilir.

Zamanlama demosunu göstermek için tüm animasyonları üç oyuncuya böldüm. Birincisi, sağdaki önizlemenin oynatılmasını kontrol etmektir . İkincisi, tüm topların ana hatlarının soldaki ve önizlemedekinin atlama animasyonunu birleştirir.

Son olarak, üçüncüsü, topların pozisyon animasyonlarını sol bir kapta birleştiren bir oyuncu. Bu oyuncu, saniyede yaklaşık 60 kare ile animasyonun sürekli bir gösteriminde topların yayılmasını sağlar.

Çözüm

Web Animasyonları API'si gibi web arayüzleri, bizim için tarayıcıların başından beri yaptığı bazı şeyleri ortaya çıkarır. Tarayıcılar, işi GPU'ya aktararak nasıl hızlı oluşturulacağını bilir. Web Animations API ile kontrol bizde. Bu kontrol biraz yabancı veya kafa karıştırıcı görünse de, onu kullanmanın da kafa karıştırıcı olması gerektiği anlamına gelmez. Zamanlama ve oynatma kontrolü anlayışıyla, bu API'yi ihtiyaçlarınıza göre evcilleştirecek araçlara sahip olursunuz. Ne kadar karmaşık olması gerektiğini tanımlayabilmelisiniz.

Daha fazla okuma

  • “Animasyon Tasarlamada Pratik Teknikler,” Sarah Drasner
  • “Hareket Hassasiyetleri İçin Azaltılmış Hareketle Tasarım” Val Head
  • “Sesli Asistanlara Alternatif Bir Ses Kullanıcı Arayüzü,” Ottomatias Peura
  • “Mobil Kullanıcı Arayüzleri İçin Daha İyi Araç İpuçları Tasarlamak,” Eric Olive