CSS Animasyon Durumunu ve Oynatma Süresini Hacklemek PlatoBlockchain Veri Zekası. Dikey Arama. Ai.

CSS Animasyon Durumunu ve Oynatma Süresini Hackleme

Yalnızca CSS Wolfenstein birkaç hafta önce yaptığım küçük bir proje. CSS 3D dönüşümleri ve animasyonları ile bir deneydi.

Esinlenen FPS demosu ve başka Wolfenstein KoduKalem, kendi versiyonumu oluşturmaya karar verdim. Orijinal Wolfenstein 1D oyununun Bölüm 9 - Kat 3'una gevşek bir şekilde dayanmaktadır.

Editör: Bu oyun, Game Over ekranından kaçınmak için kasıtlı olarak hızlı tepki vermeyi gerektiriyor.

İşte bir oynanış videosu:

[Gömülü içerik]

Özetle, projem özenle yazılmış uzun bir CSS animasyonundan başka bir şey değil. Ayrıca birkaç örnek onay kutusu hack.

:checked ~ div { animation-name: spin; }

Ortam 3B ızgara yüzlerinden oluşur ve animasyonlar çoğunlukla düz 3B ötelemeler ve döndürmelerdir. Hiçbir şey gerçekten süslü değil.

Bununla birlikte, çözülmesi özellikle zor olan iki sorun vardı:

  • Oyuncu bir düşmana tıkladığında "silah ateşleme" animasyonunu oynatın.
  • Hızlı hareket eden patron son vuruşu aldığında, dramatik bir ağır çekime girin.

Teknik düzeyde bu şu anlama geliyordu:

  • Sonraki onay kutusu işaretlendiğinde bir animasyonu yeniden oynatın.
  • Bir onay kutusu işaretlendiğinde bir animasyonu yavaşlatın.

Aslında, projemde hiçbiri düzgün bir şekilde çözülmedi! Ya geçici çözümler kullandım ya da vazgeçtim.

Öte yandan, biraz araştırmadan sonra sonunda her iki sorunun da anahtarını buldum: CSS animasyonlarını çalıştırmanın özelliklerini değiştirmek. Bu yazıda, bu konuyu daha ayrıntılı olarak inceleyeceğiz:

  • Çok sayıda etkileşimli örnek.
  • Diseksiyonlar: Her bir örnek nasıl çalışır (veya çalışmaz)?
  • Sahne arkası: Tarayıcılar animasyon durumlarını nasıl işler?

İzin ver "tuğlalarımı fırlat".

Sorun 1: Animasyonu Yeniden Oynatma

İlk örnek: "sadece başka bir onay kutusu"

İlk sezgim, çalışmayan “sadece başka bir onay kutusu ekle” idi:

Her onay kutusu ayrı ayrı çalışır, ancak ikisi birlikte çalışmaz. Bir onay kutusu zaten işaretliyse diğeri artık çalışmaz.

İşte nasıl çalıştığı (veya "çalışmadığı"):

  1. The animation-name of <div> is none varsayılan olarak.
  2. Kullanıcı bir onay kutusuna tıklar, animation-name olur spin, ve animasyon baştan başlar.
  3. Bir süre sonra kullanıcı diğer onay kutusuna tıklar. Yeni bir CSS kuralı yürürlüğe girer, ancak animation-name is yine de spin, bu, hiçbir animasyonun eklenmediği veya kaldırılmadığı anlamına gelir. Animasyon hiçbir şey olmamış gibi oynamaya devam ediyor.

İkinci örnek: "animasyonu klonlama"

Çalışan bir yaklaşım, animasyonu klonlamaktır:

#spin1:checked ~ div { animation-name: spin1; }
#spin2:checked ~ div { animation-name: spin2; }

İşte nasıl çalışır:

  1. animation-name is none Başlangıçta.
  2. Kullanıcı “Döndür!” seçeneğine tıklar, animation-name olur spin1. Animasyon spin1 yeni eklendiği için baştan başlatılır.
  3. Kullanıcı “Tekrar Döndür!” seçeneğine tıklar, animation-name olur spin2. Animasyon spin2 yeni eklendiği için baştan başlatılır.

Adım #3'te, spin1 CSS kurallarının sırası nedeniyle kaldırıldı. “Tekrar Döndür!” durumunda çalışmaz. önce kontrol edilir.

Üçüncü örnek: “aynı animasyonu eklemek”

Başka bir çalışma yaklaşımı “aynı animasyonu eklemek”tir:

#spin1:checked ~ div { animation-name: spin; }
#spin2:checked ~ div { animation-name: spin, spin; }

Bu, önceki örneğe benzer. Aslında davranışı şu şekilde anlayabilirsiniz:

#spin1:checked ~ div { animation-name: spin1; }
#spin2:checked ~ div { animation-name: spin2, spin1; }

“Tekrar Döndür!” işaretlendiğinde, eski çalışan animasyon yeni listede sezgisel olmayan ikinci animasyon haline gelir. Doğrudan bir sonuç şudur: hile işe yaramazsa animation-fill-mode is forwards. İşte bir demo:

Bunun neden böyle olduğunu merak ediyorsanız, işte bazı ipuçları:

  • animation-fill-mode is none varsayılan olarak, bu, "Oynatılmıyorsa animasyonun hiçbir etkisi yoktur" anlamına gelir.
  • animation-fill-mode: forwards; "Animasyon oynatıldıktan sonra, sonsuza kadar son ana karede kalmalıdır" anlamına gelir.
  • spin1kararı her zaman geçersizdir spin2çünkü spin1 listede daha sonra görünür.
  • Kullanıcının “Döndür!”e tıkladığını, tam bir dönüş için beklediğini ve ardından “Tekrar Döndür!”e tıkladığını varsayalım. Şu anda. spin1 zaten bitti ve spin2 sadece başlar.

Tartışma

Temel kural: mevcut bir CSS animasyonunu "yeniden başlatamazsınız". Bunun yerine, yeni bir animasyon eklemek ve oynatmak istiyorsunuz. Bu tarafından onaylanabilir W3C spesifikasyonu:

Bir animasyon başladıktan sonra bitene veya animasyon adı kaldırılana kadar devam eder.

Şimdi son iki örneği karşılaştırarak, pratikte "klonlama animasyonlarının", özellikle CSS ön işlemcisi mevcut olduğunda, genellikle daha iyi çalışması gerektiğini düşünüyorum.

Sorun 2: Yavaş Hareket

Bir animasyonu yavaşlatmanın yalnızca daha uzun bir süre ayarlamaktan ibaret olduğu düşünülebilir. animation-duration:

div { animation-duration: 0.5s; }
#slowmo:checked ~ div { animation-duration: 1.5s; }

Gerçekten de, bu işe yarar:

…ya da öyle mi?

Birkaç tweaks ile sorunu görmek daha kolay olmalı.

Evet, animasyon yavaşladı. Ve hayır, iyi görünmüyor. Onay kutusunu değiştirdiğinizde köpek (neredeyse) her zaman "atlar". Ayrıca, köpek ilk pozisyondan ziyade rastgele bir pozisyona atlıyor gibi görünüyor. Nasıl olur?

İki “gölge unsur” ekleseydik bunu anlamak daha kolay olurdu:

Her iki gölge öğesi de farklı animasyonlarla aynı animasyonları çalıştırıyor. animation-duration. Ve onay kutusundan etkilenmezler.

Onay kutusunu değiştirdiğinizde, öğe hemen iki gölge öğesinin durumları arasında geçiş yapar.

Alıntı yapmak W3C spesifikasyonu:

Animasyon çalışırken animasyon özelliklerinin değerlerinde yapılan değişiklikler, animasyonun başladığı andan itibaren bu değerlere sahipmiş gibi uygulanır.

Bu şu vatansız tarayıcıların animasyonlu değeri kolayca belirlemesini sağlayan tasarım. Gerçek hesaplama açıklanmıştır okuyun ve okuyun.

Başka Bir Deneme

Bir fikir, mevcut animasyonu duraklatmak ve ardından oradan devralan daha yavaş bir animasyon eklemektir:

div {
  animation-name: spin1;
  animation-duration: 2s;
}

#slowmo:checked ~ div {
  animation-name: spin1, spin2;
  animation-duration: 2s, 5s;
  animation-play-state: paused, running;
}

Böylece çalışır:

…ya da öyle mi?

“Slowmo!”ya tıkladığınızda yavaşlar. Ancak tam bir daire beklerseniz, bir “sıçrama” göreceksiniz. Aslında, her zaman “Slowmo!” olduğunda pozisyona atlar. tıklanır.

nedeni bizde yok from ana kare tanımlandı - ve yapmamalıyız. Kullanıcı “Slowmo!”ya tıkladığında, spin1 bir konumda duraklatılır ve spin2 tam olarak aynı pozisyonda başlar. Bu pozisyonu önceden tahmin edemeyiz… yoksa yapabilir miyiz?

Çalışan Bir Çözüm

Yapabiliriz! Özel bir özellik kullanarak, ilk animasyondaki açıyı yakalayabilir ve ardından ikinci animasyona aktarabiliriz:

div {
  transform: rotate(var(--angle1));
  animation-name: spin1;
  animation-duration: 2s;
}

#slowmo:checked ~ div {
  transform: rotate(var(--angle2));
  animation-name: spin1, spin2;
  animation-duration: 2s, 5s;
  animation-play-state: paused, running;
}

@keyframes spin1 {
  to {
    --angle1: 360deg;
  }
}

@keyframes spin2 {
  from {
    --angle2: var(--angle1);
  }
  to {
    --angle2: calc(var(--angle1) + 360deg);
  }
}

Not: @property bu örnekte kullanılan tüm tarayıcılar tarafından desteklenmez.

“Mükemmel” Çözüm

Önceki çözüm için bir uyarı var: “yavaş moddan çıkmak” iyi çalışmıyor.

İşte daha iyi bir çözüm:

Bu versiyonda, ağır çekime sorunsuz bir şekilde girilebilir veya çıkılabilir. Herhangi bir deneysel özellik de kullanılmamaktadır. Peki mükemmel çözüm mü? Evet ve hayır.

Bu çözüm, "vites değiştirmek" gibi çalışır:

  • Dişliler: iki tane var <div>s. Biri diğerinin ebeveynidir. Her ikisi de var spin animasyon ama farklı animation-duration. Elemanın son hali, her iki animasyonun da toplanmasıdır.
  • Kaydırma: Başlangıçta yalnızca bir <div> animasyonu çalışıyor. Diğeri duraklatılır. Onay kutusu değiştirildiğinde, her iki animasyon da durumlarını değiştirir.

Sonuçtan gerçekten hoşlansam da bir sorun var: spin genel olarak diğer animasyon türleri için çalışmayan animasyon.

Pratik Bir Çözüm (JS ile)

Genel animasyonlar için, biraz JavaScript ile ağır çekim işlevini elde etmek mümkündür:

Hızlı bir açıklama:

  • Animasyon ilerlemesini izlemek için özel bir özellik kullanılır.
  • Onay kutusu değiştirildiğinde animasyon "yeniden başlatılır".
  • JS kodu doğru olanı hesaplar animation-delay sorunsuz bir geçiş sağlamak için. Ben tavsiye ediyorum Bu makale negatif değerlerine aşina değilseniz animation-delay.

Bu çözümü, "animasyonu yeniden başlatma" ve "vites değiştirme" yaklaşımının bir karışımı olarak görebilirsiniz.

Burada animasyonun ilerlemesini doğru bir şekilde izlemek önemlidir. Aşağıdaki durumlarda geçici çözümler mümkündür: @property mevcut değil. Örnek olarak, bu sürüm kullanır z-index ilerlemeyi izlemek için:

Yan not: Başlangıçta, yalnızca CSS'ye yönelik bir sürüm oluşturmaya da çalıştım ancak başarılı olamadım. %100 emin olmamakla birlikte bence animation-delay is canlandırılabilir değil.

İşte minimum JavaScript içeren bir sürüm. Yalnızca "yavaş moda girmek" işe yarar.

Yalnızca çalışan bir CSS sürümü oluşturmayı başarırsanız lütfen bana bildirin!

Ağır Çekim Herhangi Bir Animasyon (JS ile)

Son olarak, birden fazla karmaşık animasyonda bile (neredeyse) herhangi bir animasyon için işe yarayan bir çözümü paylaşmak istiyorum. @keyframes:

Temel olarak, bir animasyon ilerleme izleyicisi eklemeniz ve ardından dikkatlice hesaplamanız gerekir. animation-delay yeni animasyon için Ancak bazen doğru değerleri elde etmek zor (ama mümkün) olabilir.

Örneğin:

  • animation-timing-function değil linear.
  • animation-direction değil normal.
  • birden çok değer animation-name farklı olan animation-duration's ve animation-delayVar.

Bu yöntem de açıklanmıştır okuyun için Web Animasyonları API'sı.

Teşekkürler

Yalnızca CSS projeleri ile karşılaştıktan sonra bu yola başladım. Bazıları hassas sanat eseri, ve bazıları karmaşık mekanizmalar. Benim favorilerim 3B nesneler içerenler, örneğin bu top zıplatma ve bu ambalaj küpü.

Başlangıçta, bunların nasıl yapıldığına dair hiçbir fikrim yoktu. Daha sonra okudum ve çok şey öğrendim Ana Tudor'un bu güzel öğreticisi.

Görünüşe göre, CSS ile 3B nesneler oluşturmak ve canlandırmak, CSS ile yapmaktan çok farklı değil. karıştırıcı, sadece biraz farklı bir lezzetle.

Sonuç

Bu yazıda CSS animasyonlarının davranışını inceledik. animate-* mülkiyet değiştirilir. Özellikle “animasyonu tekrar oynatma” ve “yavaş animasyon animasyonu” için çözümler geliştirdik.

Umarım bu makaleyi ilginç bulursunuz. Lütfen düşüncelerinizi bildirin!

Zaman Damgası:

Den fazla CSS Püf Noktaları