Chrome, kaydırmayla tetiklenen animasyonlar sunmuştur ve bunu yapan ilk tarayıcıdır. Chrome 146'ya güncelleme yaparsanız, bir karenin arka planının 300 ms boyunca soluklaştığı ancak yalnızca öğenin tamamı görünüm alanı içinde olduğunda aşağıdaki demoyu görüntüleyebilirsiniz.
CodePen Yerleştirme Geri Dönüşü
Bu, kaydırmayla tetiklenen animasyonların çalışma biçiminden biraz farklıdır, bu nedenle bu makalede bunları karşılaştıracağım ve ardından kaydırmayla tetiklenen animasyonların nasıl çalıştığını size göstereceğim.
Kaydırmayla tetiklenen animasyonlar ve kaydırmayla yönlendirilen animasyonlar
Önemli Gelişmeler
Kaydırmayla tetiklenen animasyonlar, belirli bir kaydırma eşiği aşıldığında sabit bir süre boyunca oynatılır. (JavaScript'in Kesişme Gözlemcisi API'sini düşünün, ancak CSS animasyonları için.)
Teknik Analiz
Bu, animasyon ilerlemesinin kaydırma ilerlemesi (animation-timeline: Scroll() ) veya kesişme derecesi (animation-timeline: view() ) ile senkronize edildiği ve dolayısıyla süresi olmayan kaydırma odaklı animasyonlardan farklıdır.
Temel kaydırmayla tetiklenen animasyon örneği
Gelecekte Ne Bekleniyor?
Anahtar kısım, animasyon-zaman çizelgesi: view() yerine timeline-trigger: view()'dır; bu, öğenin ne kadar içinde olduğunu ölçmek ve buna göre bir şeyler yapmak yerine öğenin eşik içinde olmasını bekler. Ancak arka planı ayarlayan gerçek @keyframes animasyonuyla başlayalım:
/* Animasyonu tanımlayın */ @keyframes fade-bg-in { ila { arka plan: currentColor; } }
.square'de 300 ms süreyle ayarlanır:
.square { /* Animasyonu bildir */ animasyon: fade-bg-in 300ms; }
Sistem Güvenliği
Varsayılan olarak, CSS animasyonları bildirim uygulandığında tetiklenir, ancak aşağıdaki genişletilmiş kod parçasında timeline-trigger bu davranışın üzerine yazar. Artık animasyon, öğe view() işlevine girdiğinde tetiklenir. --trigger basitçe tetikleyici için bir tanımlayıcı görevi gören kesikli bir kimliktir, oysa giriş %100 çıkış %0 bir zaman çizelgesi aralığıdır. Zaman çizelgesi aralığı, animasyonun etkinleştirildiği ve etkin kalmasına izin verilen kaydırma bölgesini belirtir.
Bu durumda, animasyon, .square'in alt kenarı ( giriş 100% ) girdiğinde tetiklenir ve üst kenar kaydırma portundan çıktığında ( çıkış 0% ) tetiklemeyi kaldırır (hala çalıştığını varsayarak). Açıklık getirmek gerekirse, %0 girişi, üst kenar girdiğinde animasyonu tetikleyecektir. entry, kaydırma portunun alt kısmından gelen öğeyi yönetirken, çıkış, kaydırma portunun üst kısmından çıkmasını yönetir. Biraz kafa karıştırıcı ama fazla açıklamazsam anlaşılması daha kolay olur.
Uzmanların Görüşleri
.square { /* Animasyonu bildir */ animasyon: fade-bg-in 300ms; /* Animasyon tetikleme koşulları */ timeline-trigger: --trigger view() giriş %100 çıkış %0; }
Animation-trigger için öncelikle hangi tetikleyiciden bahsettiğimizi belirliyoruz ve ardından bazı ayarları beyan ediyoruz (örn. play-forwards):
Nasıl Önlem Alınmalı?
.square { /* Animasyonu bildir */ animasyon: fade-bg-in 300ms; /* Animasyon tetikleme koşulları */ timeline-trigger: --trigger view() giriş %100 çıkış %0; /* Animasyon tetikleyici ayarları */ Animation-trigger: --trigger play-forwards; }
Detaylar ve Etkileri
CodePen Yerleştirme Geri Dönüşü
Play-forwards anahtar sözcüğü, kare tamamen görünür hale geldiğinde animasyonu tetikler ve animasyon için bir doldurma modu bildirmediğimiz için (animasyon-doldurma modunu kullanarak veya animasyon kısayolunun bir parçası olarak), bu da karenin daha sonra arka planı tutmayacağı anlamına gelir, animasyon daha çok bir flaştır.
Dolayısıyla farklı sonuçlar elde etmek için bunu temel almamız gerekiyor.
Sonuç ve Değerlendirme
İlk olarak, animasyon doldurma modu için veya animasyon kısaltmasının bir parçası olarak farklı doldurma modu değerlerinin ne yaptığının bir özeti:
ileriye doğru : stiller animasyondan sonra korunur.
stiller animasyondan sonra korunur. geriye doğru : stiller animasyondan önce uygulanır.
stiller animasyondan önce uygulanır. her ikisi de: her iki davranış da uygulanır.
Şimdi,
.square { animasyon: 300 ms ileri doğru solma-bg-in; timeline-trigger: --trigger view() giriş %100 çıkış %0; animasyon-tetikleyici: --ileriye doğru oynatmayı tetikleyin; }
CodePen Yerleştirme Geri Dönüşü
Bu, stillerin korunmasına neden olur, ancak kare kısmen veya tamamen görünüm alanından çıkıp tekrar girerse, animasyon yeniden başlar ve bu, animasyonun nasıl bittiğine bağlı olarak bir flaşa neden olabilir; bu örnekte de böyle olur.
Bunu çözmenin iki farklı yolu var…
"Kilitleme" yöntemi: İleriye doğru oynatma yerine bir kez oynatmayı kullanın; bu, ileriye doğru ile birleştirildiğinde animasyonun bir kez oynatılmasına ve hiçbir zaman yeniden başlatılmamasına neden olur. t ve daha sonra stilleri koruyarak.
.square { /* Bir kez oynat */ Animation-trigger: --trigger play-once; /* Stilleri koru */ animasyon: 300 ms ileri doğru fade-bg-in; timeline-trigger: --trigger view() giriş %100 çıkış %0; }
CodePen Yerleştirme Geri Dönüşü
"İleri-geri" yöntemi: ileri oynatma-geri oynatma, öğeyi tamamen görünür olduğunda normal şekilde, artık tam olarak görünür olmadığında ise ters yönde hareketlendirir. Öğe ileriye doğru olduğu kadar geriye doğru da sorunsuz bir şekilde hareket ettiğinden flaş yoktur. Ayrıca animasyonun yönü değişse de dolgu modu her ikisine de ayarlanmak yerine ileri konumda kalabiliyor.
ileri oynatma "animasyonu %0'dan %100'e oynatmak" anlamına gelirken geri oynatma "animasyonu %100'den %0'a oynatmak" anlamına gelir. Bu arada, daha önce de belirttiğim gibi, ileriye doğru doldurma modu "animasyon tamamlandığında stilleri korumak" anlamına gelir; bu, son ana karenin %0 veya %100 olmasından bağımsızdır.
.square { /* Uygun şekilde ileri ve geri oynatın */ Animation-trigger: --trigger play-forwards play-backwards; /* Stilleri her iki şekilde de koruyun */ animasyon: fade-bg-in 300ms ileri; timeline-trigger: --trigger view() giriş %100 çıkış %0; }
CodePen Yerleştirme Geri Dönüşü
ileri oynat, bir kez oynat ve geri oynat,
Bu
Birden fazla öğeyi kaydırmayla tetikleme
Animasyon eylemlerinden, doldurma modlarından, zaman çizelgesi aralıklarından ve belki daha fazlasından oluşan kaydırmayla tetiklenen animasyonlar aşırı karmaşık görünebilir, ancak bu mekanizmaların ayrıştırılmış olması, esnekliği korurken mantığı yeniden kullanmamıza, tekrarı azaltmamıza ve mekaniği tasarım sistemi dostu hale getirmemize olanak tanır.
Bu sefer üç kare düşünün ve biraz daha karmaşıklık sağlamak için ölçeği beyan ediyoruz: %70 (başlangıca göre animasyonlar) ve iki döner animasyon tanımlıyoruz.
/* Animasyonları tanımlayın */ @keyframes intensify { to { Scale: başlangıç; arka plan: currentColor; } } @ana kareler sola döndür { ila { döndür: -5 derece; } } @keyframes sağa döndür { ila { döndür: 5 derece; } } .kare { /* Başlangıç değerini ayarla */ ölçek: %70; }
Bundan sonrası daha çok aynıdır ve açıkçası daha karmaşık bir örnek olsa da, değerleri kısa özelliklerle birleştirebilmek ve bunları uzun el özelliklerine ayırabilmek, ayrıca farklı mekanizmaların ayrıştırılmış doğası, esnekliği kolaylaştırır ama aynı zamanda yeniden kullanılabilirliği de kolaylaştırır (bu durumda, aynı animasyon tetikleme ayarlarını kullanarak çeşitli animasyonları kademeli hale getirmek için):
.square { /* Başlangıç değerini ayarlayın */ ölçek: %70; /* Animasyon adını tanımlayın */ --base-animation: intensify; /* Animasyonu bildir */ animasyon: var(--base-animation) 300ms ileri; /* Animasyon tetikleyici ayarlarını tanımlayın */ --animation-trigger: --trigger ileri oynat oynat-geriye doğru; /* Yoğunlaştırmak için tanımlayın, ardından döndürme animasyonlarından biri için bildirin */ Animation-trigger: var(--animation-trigger), var(--animation-trigger); /* Animasyon tetikleme koşullarını bildir (zaman çizelgesi aralıkları olmadan) */ timeline-trigger: --trigger view(); /* Aktif aralık sonunu bildir */ timeline-trigger-active-range-end: normal; /* Diğer animasyonları ekleyin */ &.rotate-left { animasyon-adı: var(--base-animation), Rotate-left; } &.rotate-right { animasyon-adı: var(--base-animation), Rotate-right; } /* Aktivasyon aralıklarını kademelendir */ &:first-child { timeline-trigger-activation-range-start: entry 33,3333%; } &:nth-child(2) { zaman çizelgesi-tetikleyici-aktivasyon-aralığı-başlangıç: giriş %66,6666; } &:son-çocuk { zaman çizelgesi-tetikleyici-aktivasyon-aralığı-başlangıç: giriş %99,9999; } }
CodePen E mbed Geri Dönüş
Animasyonları kademeli hale getirmek için sibling-count() ve sibling-index() (Firefox desteği olmayan) kullanan daha temiz, daha sağlam bir sürüm:
CodePen Yerleştirme Geri Dönüşü
Bu versiyonda, her bir karede zaman çizelgesi-tetikleyici-aktivasyon-aralığı-başlangıç değerini ayarlamak yerine, yalnızca .square'i hedefliyoruz ve giriş değerlerini anında hesaplıyoruz:
/* Maksimum giriş ÷ kare sayısı */ --stagger-interval: calc(100% / sibling-count()); /* Mevcut karenin indeksi × kademe aralığı */ --entry: calc(sibling-index() * var(--stagger-interval)); /* Animasyon tetikleme koşullarını bildirin */ timeline-trigger: --trigger view() entry var(--entry) çıkış 0%;
Bir elementin diğer elementleri tetiklemesini sağlamak
Bu durumda, tetikleyiciyi ve aralıklarını ilk kareye kaydıracağız ve diğer karelerin kademeli bir animasyon gecikmesine göre takip etmesini sağlayacağız. Gördüğünüz gibi, tüm animasyonlar, ilk karenin %50'si görünüm alanına ( view() ) girdiğinde (giriş %50) animasyon tetikleyicisi tarafından tetiklenir. Animation-trigger, timeline-trigger tarafından tetiklenir çünkü kesikli kimlik (uygun şekilde --trigger olarak adlandırılır) bunları birbirine bağlar:
/* Animasyonları tanımlayın */ @keyframes intensify { to { Scale: başlangıç; arka plan: currentColor; } } @ana kareler sola döndür { ila { döndür: -5 derece; } } @keyframes sağa döndür { ila { döndür: 5 derece; } } .kare { /* Başlangıç değerini ayarla */ ölçek: %70; /* Animasyon adını tanımlayın */ --base-animation: intensify; /* Maksimum gecikme ÷ kare sayısı */ --stagger-interval: calc(300ms / sibling-count()); /* Mevcut karenin indeksi × kademelendirme aralığı */ --animation-delay: calc(sibling-index() * var(--stagger-interval)); /* Animasyonu bildir */ animasyon: var(--base-animation) 300ms var(--animation-delay) forwards; /* Animasyon tetikleyici ayarlarını tanımlayın */ --animation-trigger: --trigger ileri oynat oynat-geriye doğru; /* Yoğunlaştırmak için tanımlayın, ardından döndürme animasyonlarından biri için bildirin */ Animation-trigger: var(--animation-trigger), var(--animation-trigger); &:first-child { /* Animasyon tetikleme koşullarını bildirin */ timeline-trigger: --trigger view() girişi %50; /* Aktif aralık sonunu bildir */ timeline-trigger-active-range-end: normal; } /* Diğer animasyonları ekleyin */ &.rotate-left { animasyon-adı: var(--base-animation), rotary-left; } &.rotate-right { animasyon-adı: var(--base-animation), Rotate-right; } }
CodePen Yerleştirme Geri Dönüşü
Bir dezavantajı, animasyon tetikleyicisi geriye oynatma modundayken animasyonların sendelememesidir. Bunun nedeni, animasyon tersine çevrildiğinde gecikmenin de buna dahil olduğunu düşünüyorum. Bu bana bir gözden kaçırma gibi görünüyor, özellikle de animasyon yönü: ters durumunda durum böyle değil, ancak bu konuda tamamen yanılıyor olabilirim.
Zaman çizelgesi aralıklarını anlama
Zaman çizelgesi aralıkları kaydırmayla tetiklenen animasyonların büyük bir bölümünü oluşturur ancak bunlar ayrı bir mekanizmadır. Kaydırma odaklı animasyonlar için, animasyon aralığını ve onun uzun el özelliklerini isteyeceksiniz. Kaydırmayla tetiklenen animasyonlarda sözdizimi temelde aynıdır ancak farklı özellikler ve iki farklı aralık kullanır. Etkinleştirme aralığı, animasyonun tetikleneceği kaydırma bölgesini belirlerken, etkin aralık, animasyonun tutulacağı bölgeyi belirler (artık etkinleştirme aralığında olmasa bile).
Zaman çizelgesi aralıkları biraz ağır. Bununla birlikte, view() girişi %100 çıkış %0 (tamamen görünür olduğunda) ve view() içermesi (aynı ama aynı zamanda görünüm alanından daha büyükse) çoğu zaman yeterli olacaktır.
Ancak konuya dalmaya meraklıysanız, animasyon aralığı kaydırma odaklı animasyonlar için olmasına rağmen daha hafiftir ve zaman çizelgesi aralıklarının acemi düzeyinde anlaşılmasını sağlar. Bundan sonra, kaydırmayla tetiklenen bu animasyonlar bağlamında zaman çizelgesi aralıklarının birçok karmaşıklığını ele almak için Animasyon Tetikleyicileri spesifikasyonunu okumanızı öneririm.
Kaydırmayla tetiklenen animasyonların kendine has başka bir bileşeni de view() işlevidir, ancak bunu burada özetlemek daha kolaydır. Temel olarak, kaydırmayla tetiklenen animasyonlar söz konusu olduğunda view(), görünüm portudur. Dolayısıyla, 5rem'lik yapışkan bir başlığınız varsa, view(y 0 5rem), zaman çizelgesi aralığını y ekseni boyunca faktör haline getirir.
Kaydırmayla tetiklenen animasyonlar, kaydırmayla tetiklenen animasyonlara benzedikleri için yanıltıcı olabilir; kaydırmayla tetiklenen animasyonlara özgü CSS özelliklerine ek olarak eski CSS özelliklerinin (temel olarak animasyon) yanı sıra diğer yeni özelliklerin (kesikli kimlikler, view(), zaman çizelgesi aralıkları) mekaniklerini de kullanırlar. Aynı anda pek çok şey oluyor.
Dürüst olmak gerekirse onlar hakkında ne hissettiğimden emin değilim. Onlar kesinlikle harika, eğlenceli ve kullanışlı, ama aynı zamanda karmaşıklar ve onlardan gerçekten övünmeye başlamam biraz zaman alacak.