Chromium 84'te Web Animations API iyileştirmeleri

Sözlerle animasyonları koordine etme, değiştirilebilir animasyonlarla performans iyileştirmeleri, karma modlarla daha akıcı animasyonlar ve daha fazlası.

Kevin Ellis
Kevin Ellis

Yayınlanma tarihi: 27 Mayıs 2020

Doğru kullanıldığında animasyonlar, markanızı kullanıcı algısını ve hafızasını iyileştirir, kullanıcı işlemlerine rehberlik eder ve kullanıcıların dijital alanda bağlam bilgisi edinmesine yardımcı olarak uygulamanızda gezinmelerine yardımcı olur.

Web Animasyonları API, geliştiricilerin JavaScript ile zorunlu animasyonlar yazmasını sağlayan bir araçtır. Hem CSS animasyon hem de geçiş uygulamalarını desteklemek, gelecekte efektlerin geliştirilmesini ve mevcut efektlerin derlenmesini ve zamanlanmasını sağlamak için yazılmıştır.

Firefox ve Safari, spesifikasyon özelliklerinin tamamını zaten uygulamış olsa da Chromium 84, daha önce desteklenmeyen bir dizi özelliği Chrome ve Edge'e getirerek tarayıcılar arası birlikte çalışabilirliği sağlar.

Web Animations API, ilk olarak Temmuz 2014'te Chromium 36 sürümünde kullanıma sunulmuştur. Bu özellik, Temmuz 2020'de kullanıma sunulacak 84 sürümünde tamamlanacak.
Chromium'daki Web Animations API'nin uzun geçmişi.

Başlarken

@keyframe kurallarını kullandıysanız Web Animations API'yi kullanarak animasyon oluşturmak size tanıdık gelecektir. Öncelikle bir Ana Çizgi Nesnesi oluşturmanız gerekir. CSS'de böyle görünebilir:

@keyframes openAnimation {
  0% {
    transform: scale(0);
  }
  100% {
    transform: scale(1);
  }
}

JavaScript'te böyle görünür:

const openAnimation = [
  { transform: 'scale(0)' },
  { transform: 'scale(1)' },
];

CSS'de animasyon parametrelerini ayarladığınız yerler:

.modal {
  animation: openAnimation 1s 1 ease-in;
}

JS'de ayarlarsınız:

document.querySelector('.modal').animate(
    openAnimation, {
      duration: 1000, // 1s
      iterations: 1, // single iteration
      easing: 'ease-in' // easing function
    }
);

Kod miktarı yaklaşık olarak aynıdır ancak JavaScript'te, yalnızca CSS'de sahip olmadığınız birkaç süper güç elde edersiniz. Etkileri sıralama ve oynatma durumlarını daha iyi kontrol etme de bu değişikliklerden bazılarıdır.

element.animate()'ten fazla

Ancak bu güncellemeyle birlikte Web Animations API artık element.animate() kullanılarak oluşturulan animasyonlarla sınırlı değil. CSS animasyonları ve geçişlerini de değiştirebiliriz.

getAnimations(), element.animate() kullanılarak mı yoksa CSS kuralları (CSS animasyonu veya geçişi) kullanılarak mı oluşturulduğuna bakılmaksızın bir öğedeki tüm animasyonları döndüren bir yöntemdir. Bunun nasıl göründüğüne dair bir örnek:

Öncelikle, geçişin hangi noktadan yapılacağını belirlemek için geçişin anahtar karelerini "get". Ardından, geçiş efekti etkinleştirerek iki yeni opaklık animasyonu oluşturursunuz. Geçiş tamamlandıktan sonra kopyayı silersiniz.

Animasyonları sözlerle koordine etme

Chromium 84'te artık animation.ready ve animation.finished olmak üzere, sözle kullanılabilir iki yönteminiz var.

  • animation.ready, bekleyen değişikliklerin geçerlilik kazanmasını (yani oynatma ve duraklatma gibi oynatma kontrolü yöntemleri arasında geçiş yapma) beklemenizi sağlar.
  • animation.finished, bir animasyon tamamlandığında özel JavaScript kodu çalıştırmanızı sağlar.

Örneğimize devam ederek animation.finished ile koordineli bir animasyon zinciri oluşturun. Burada, dikey bir dönüşüm (scaleY), ardından yatay bir dönüşüm (scaleX) ve ardından bir alt öğede opaklık değişikliği vardır:

Açılan bir modal öğeye dönüşümler ve opaklık uygulama. Codepen'de Demoyu Görün
const transformAnimation = modal.animate(openModal, openModalSettings);
transformAnimation.finished.then(() => { text.animate(fadeIn, fadeInSettings)});

Zincirdeki bir sonraki animasyon grubunu yürütmeden önce bu animasyonlar animation.finished.then() kullanılarak zincirlenmiştir. Bu sayede animasyonlar sırayla görünür ve hatta farklı seçenekler (ör. hız ve kolaylık) ayarlayarak farklı hedef öğelere efekt uygulayabilirsiniz.

CSS'de bu, özellikle birden fazla öğeye benzersiz ancak sıralı animasyonlar uygulandığında yeniden oluşturmak zordur. @keyframe kullanmanız, animasyon yerleştirmek için doğru zamanlama yüzdelerini sıralamanız ve animasyonları sırayla tetiklemeden önce animation-delay kullanmanız gerekir.

Örnek: Oynat, duraklat ve geri oynat

Açılabilir olanları kapatın. Neyse ki Chromium 39'dan beri Web Animations API, animasyonlarımızı oynatma, duraklatma ve geri oynatma olanağı sunuyor.

Daha önce gösterilen animasyonu .reverse() düğmesini tekrar tıklayarak pürüzsüz ve ters bir animasyona dönüştürebilirsiniz. Bu sayede, modalimiz için daha sorunsuz ve bağlama daha uygun bir etkileşim oluşturabilirsiniz.

Düğme tıklandığında açılan ve kapanan bir modal pencere örneği. Glitch'te Demoyu Görüntüleyin

Oynatma bekleyen iki animasyon (openModal ve satır içi bir opaklık dönüşümü) oluşturabilir, ardından animasyonlardan birini duraklatarak diğeri bitene kadar geciktirebilirsiniz. Ardından, oynamadan önce her birinin bitmesini beklemek için promises'i kullanabilirsiniz. Son olarak, bir işaretin ayarlanıp ayarlanmadığını kontrol edebilir ve ardından her animasyonu tersine çevirebilirsiniz.

Örnek: Kısmi anahtar karelerle dinamik etkileşimler

Fare tıklamasıyla animasyonu yeni bir konuma ayarlayan yeniden hedefleme örneği. Glitch'te Demoyu Görüntüleyin
selector.animate([{transform: `translate(${x}px, ${y}px)`}],
    {duration: 1000, fill: 'forwards'});

Bu örnekte yalnızca bir animasyon karesi vardır ve başlangıç konumu belirtilmemiştir. Bu, kısmi anahtar karelerin kullanımına örnektir. Fare işleyici burada birkaç işlem yapar: Yeni bir bitiş konumu belirler ve yeni bir animasyon tetikler. Yeni başlangıç konumu, mevcut temel konumdan tahmin edilir.

Mevcut geçişler devam ederken yeni geçişler tetiklenebilir. Bu durumda, mevcut geçiş kesintiye uğrar ve yeni bir geçiş oluşturulur.

Değiştirilebilir animasyonlarla performans iyileştirmeleri

'mousemove' gibi etkinliklere dayalı animasyonlar oluşturulurken her seferinde yeni bir animasyon oluşturulur. Bu durum, belleği hızla tüketebilir ve performansı düşürebilir. Bu sorunu gidermek için Chromium 83'te değiştirilebilir animasyonlar kullanıma sunuldu. Bu animasyonlar, bitmiş animasyonların değiştirilebilir olarak işaretlendiği ve başka bir bitmiş animasyonla değiştirilirse otomatik olarak kaldırıldığı otomatik temizlemeyi etkinleştirir. Aşağıdaki örneği inceleyin:

Fare hareket ettiğinde animasyonlu bir kuyruk çizgisi gösterilir. Glitch'te Demoyu Görün
elem.addEventListener('mousemove', evt => {
  rectangle.animate(
    { transform: translate(${evt.clientX}px, ${evt.clientY}px) },
    { duration: 500, fill: 'forwards' }
  );
});

Fare her hareket ettiğinde tarayıcı, kuyruklu yıldız izindeki her topun konumunu yeniden hesaplar ve bu yeni nokta için bir animasyon oluşturur. Tarayıcı artık aşağıdaki durumlarda eski animasyonları kaldıracağını (değiştirmeyi etkinleştireceğini) biliyor:

  1. Animasyon sona erer.
  2. Kompozit sıralamada daha üstte yer alan ve tamamlanmış bir veya daha fazla animasyon var.
  3. Yeni animasyonlar aynı özellikleri canlandırıyor.

Kaldırılan her animasyonla bir sayıcıyı toplayarak sayıcıyı tetiklemek için anim.onremove'ü kullanarak tam olarak kaç animasyonun değiştirildiğini görebilirsiniz.

Animasyon kontrolünü daha da ileri götürmek için kullanabileceğiniz birkaç ek özellik ve yöntem vardır:

  • animation.replaceState, bir animasyonun etkin, kalıcı veya kaldırılmış olup olmadığını izlemenizi sağlar.
  • animation.commitStyles(), bir öğenin stilini temel stile göre günceller ve öğedeki tüm animasyonları kompozit sırada günceller.
  • animation.persist(), bir animasyonu değiştirilemez olarak işaretler.

Birleştirilmiş modlarla daha akıcı animasyonlar

Web Animations API ile artık animasyonlarınızın birleşik modunu ayarlayabilirsiniz. Bu sayede, varsayılan "değiştir" moduna ek olarak animasyonlarınız eklemeli veya kümülatif olabilir. Kompozit modlar, geliştiricilerin farklı animasyonlar yazmasına ve efektlerin nasıl birleştirileceği üzerinde kontrol sahibi olmasına olanak tanır. Artık üç kompozit mod desteklenmektedir: 'replace' (varsayılan mod), 'add' ve 'accumulate'.

Geliştiriciler, animasyonları birleştirirken kısa ve farklı efektler yazabilir ve bunların bir arada nasıl göründüğünü görebilir. Aşağıdaki örnekte, her kutuya bir rotasyon ve ölçek anahtar karesi uyguluyoruz. Tek ayar, seçenek olarak eklenen birleştirme modudur:

Varsayılan, ekleme ve toplama karma modlarını gösteren bir demo. Glitch'te Demoyu Görün

Varsayılan 'replace' birleştirme modunda, nihai animasyon dönüştürme özelliğini değiştirir ve rotate(360deg) scale(1.4) değerinde sona erer. 'add' için birleştir, döndürmeyi ekler ve ölçeği çarpar. Sonuç olarak rotate(720deg) scale(1.96) nihai durumu elde edilir. 'accumulate', dönüşümleri birleştirerek rotate(720deg) scale(1.8) değerini oluşturur. Bu karma modların ayrıntıları hakkında daha fazla bilgi için Web Animasyonları spesifikasyonundaki CompositeOperation ve CompositeOperationOrAuto dizelerini inceleyin.

Aşağıdaki kullanıcı arayüzü öğesi örneğine göz atın:

Üzerine iki birleştirilmiş animasyon uygulanmış, sıçrayan bir açılır menü. Glitch'te Demoyu Görün

Burada iki top animasyonu birleştirilmiştir. İlki, sayfanın üst kısmından kaydırma efekti olarak açılır menüyü menünün tam yüksekliğine kadar hareket ettiren bir makro animasyondur. İkincisi ise, mikro animasyon olarak, alt kısma ulaştığında biraz sıçrama uygular. 'add' karma modu, daha sorunsuz bir geçiş sağlar.

const dropDown = menu.animate(
    [
      { top: `${-menuHeight}px`, easing: 'ease-in' },
      { top: 0 }
    ], { duration: 300, fill: 'forwards' });

  dropDown.finished.then(() => {
    const bounce = menu.animate(
      [
        { top: '0px', easing: 'ease-in' },
        { top: '10px', easing: 'ease-out' },
        { ... }
      ], { duration: 300, composite: 'add' });
  });

Web Animasyonları API'si için sırada ne var?

Bunların tümü, günümüz tarayıcılarında animasyon özelliklerine eklenen heyecan verici özelliklerdir. Daha da fazlası yolda. Gelecekte kullanıma sunulacak özellikler hakkında daha fazla bilgi edinmek için aşağıdaki teknik özelliklere göz atın: