Meretas Status Animasi CSS dan Waktu Pemutaran Intelijen Data PlatoBlockchain. Pencarian Vertikal. Ai.

Meretas Status Animasi CSS dan Waktu Pemutaran

Wolfenstein khusus CSS adalah proyek kecil yang saya buat beberapa minggu yang lalu. Itu adalah eksperimen dengan transformasi dan animasi 3D CSS.

Terinspirasi oleh demo FPS dan lain Wolfenstein Code Pen, saya memutuskan untuk membuat versi saya sendiri. Ini secara longgar didasarkan pada Episode 1 โ€“ Lantai 9 dari game 3D Wolfenstein asli.

Editor: Game ini sengaja membutuhkan reaksi cepat untuk menghindari layar Game Over.

Berikut adalah video pemutarannya:

[Embedded content]

Singkatnya, proyek saya tidak lain adalah animasi CSS panjang yang ditulis dengan hati-hati. Ditambah beberapa contoh dari peretasan kotak centang.

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

Lingkungan terdiri dari wajah kisi 3D dan animasinya sebagian besar adalah terjemahan dan rotasi 3D biasa. Tidak ada yang benar-benar mewah.

Namun, dua masalah sangat sulit untuk dipecahkan:

  • Mainkan animasi "penembakan senjata" setiap kali pemain mengklik musuh.
  • Saat bos yang bergerak cepat mendapat pukulan terakhir, masukkan gerakan lambat yang dramatis.

Pada tingkat teknis, ini berarti:

  • Putar ulang animasi saat kotak centang berikutnya dicentang.
  • Memperlambat animasi, saat kotak centang dicentang.

Faktanya, tidak ada yang diselesaikan dengan benar dalam proyek saya! Saya akhirnya menggunakan solusi atau menyerah begitu saja.

Di sisi lain, setelah beberapa penggalian, akhirnya saya menemukan kunci untuk kedua masalah: mengubah properti menjalankan animasi CSS. Pada artikel ini, kita akan mengeksplorasi lebih lanjut tentang topik ini:

  • Banyak contoh interaktif.
  • Dissections: bagaimana setiap contoh bekerja (atau tidak bekerja)?
  • Di balik layar: bagaimana browser menangani status animasi?

Ijinkan aku โ€œlemparkan batu bata sayaโ€.

Masalah 1: Memutar Ulang Animasi

Contoh pertama: "hanya kotak centang lain"

Intuisi pertama saya adalah "tambahkan saja kotak centang lain", yang tidak berfungsi:

Setiap kotak centang berfungsi secara individual, tetapi tidak keduanya bersama-sama. Jika satu kotak centang sudah dicentang, yang lain tidak lagi berfungsi.

Begini cara kerjanya (atau "tidak berfungsi"):

  1. Grafik animation-name of <div> is none secara default
  2. Pengguna mengklik satu kotak centang, animation-name menjadi spin, dan animasi dimulai dari awal.
  3. Setelah beberapa saat, pengguna mengklik kotak centang lainnya. Aturan CSS baru berlaku, tapi animation-name is masih spin, yang berarti tidak ada animasi yang ditambahkan atau dihapus. Animasi terus diputar seolah-olah tidak ada yang terjadi.

Contoh kedua: "mengkloning animasi"

Salah satu pendekatan yang berfungsi adalah mengkloning animasi:

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

Berikut adalah cara kerjanya:

  1. animation-name is none mulanya.
  2. Pengguna mengklik "Putar!", animation-name menjadi spin1. Animasi spin1 dimulai dari awal karena baru saja ditambahkan.
  3. Pengguna mengklik "Putar lagi!", animation-name menjadi spin2. Animasi spin2 dimulai dari awal karena baru saja ditambahkan.

Perhatikan bahwa pada Langkah #3, spin1 dihapus karena urutan aturan CSS. Ini tidak akan bekerja jika "Putar lagi!" diperiksa terlebih dahulu.

Contoh ketiga: "menambahkan animasi yang sama"

Pendekatan kerja lainnya adalah "menambahkan animasi yang sama":

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

Ini mirip dengan contoh sebelumnya. Anda sebenarnya dapat memahami perilaku dengan cara ini:

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

Perhatikan bahwa ketika โ€œPutar lagi!โ€ dicentang, animasi lama yang berjalan menjadi animasi kedua dalam daftar baru, yang mungkin tidak intuitif. Konsekuensi langsungnya adalah: triknya tidak akan berhasil jika animation-fill-mode is forwards. Berikut demonya:

Jika Anda bertanya-tanya mengapa hal ini terjadi, berikut adalah beberapa petunjuknya:

  • animation-fill-mode is none secara default, yang berarti "Animasi tidak berpengaruh sama sekali jika tidak diputar".
  • animation-fill-mode: forwards; berarti "Setelah animasi selesai diputar, itu harus tetap berada di keyframe terakhir selamanya".
  • spin1keputusannya selalu ditimpa spin2karena spin1 muncul kemudian dalam daftar.
  • Misalkan pengguna mengklik "Putar!", menunggu putaran penuh, lalu mengklik "Putar lagi!". Saat ini. spin1 sudah selesai, dan spin2 baru saja dimulai.

Diskusi

Aturan praktis: Anda tidak dapat "memulai ulang" animasi CSS yang ada. Sebagai gantinya, Anda ingin menambahkan dan memainkan animasi baru. Ini dapat dikonfirmasi oleh spesifikasi W3C:

Setelah animasi dimulai, itu berlanjut hingga berakhir atau nama animasi dihapus.

Sekarang membandingkan dua contoh terakhir, saya pikir dalam praktiknya, "animasi kloning" seharusnya sering bekerja lebih baik, terutama ketika praprosesor CSS tersedia.

Masalah 2: Gerakan Lambat

Orang mungkin berpikir bahwa memperlambat animasi hanyalah masalah pengaturan yang lebih lama animation-duration:

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

Memang, ini berfungsi:

โ€ฆ atau apakah itu?

Dengan beberapa penyesuaian, seharusnya lebih mudah untuk melihat masalahnya.

Ya, animasinya melambat. Dan tidak, itu tidak terlihat bagus. Anjing (hampir) selalu "melompat" saat Anda mengaktifkan kotak centang. Selain itu, anjing tampaknya melompat ke posisi acak daripada yang awal. Bagaimana bisa?

Akan lebih mudah untuk memahaminya jika kita memperkenalkan dua "elemen bayangan":

Kedua elemen bayangan menjalankan animasi yang sama dengan yang berbeda animation-duration. Dan mereka tidak terpengaruh oleh kotak centang.

Saat Anda mengaktifkan kotak centang, elemen segera beralih di antara status dua elemen bayangan.

Mengutip spesifikasi W3C:

Perubahan pada nilai properti animasi saat animasi berjalan berlaku seolah-olah animasi memiliki nilai tersebut sejak dimulai.

Ini mengikuti tanpa kewarganegaraan design, yang memungkinkan browser menentukan nilai animasi dengan mudah. Perhitungan sebenarnya dijelaskan di sini dan di sini.

Upaya lain

Satu ide adalah untuk menjeda animasi saat ini, lalu menambahkan animasi lebih lambat yang mengambil alih dari sana:

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

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

Jadi ini berfungsi:

โ€ฆ atau apakah itu?

Itu melambat ketika Anda mengklik "Slowmo!". Tetapi jika Anda menunggu satu lingkaran penuh, Anda akan melihat "lompatan". Sebenarnya, selalu melompat ke posisi ketika "Slowmo!" diklik.

Alasannya adalah kami tidak memiliki from keyframe didefinisikan โ€“ dan kita seharusnya tidak melakukannya. Ketika pengguna mengklik "Slowmo!", spin1 dijeda di beberapa posisi, dan spin2 dimulai pada posisi yang sama persis. Kita tidak bisa memprediksi posisi itu sebelumnya โ€ฆ atau bisakah kita?

Solusi yang Bekerja

Kita dapat! Dengan menggunakan properti kustom, kita dapat menangkap sudut di animasi pertama, lalu meneruskannya ke animasi kedua:

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);
  }
}

Catatan: @property digunakan dalam contoh ini, yaitu tidak didukung oleh semua browser.

Solusi "Sempurna"

Ada peringatan untuk solusi sebelumnya: "keluar dari slowmo" tidak berfungsi dengan baik.

Inilah solusi yang lebih baik:

Dalam versi ini, gerakan lambat dapat masuk atau keluar dengan mulus. Tidak ada fitur eksperimental yang digunakan. Jadi apakah itu solusi yang tepat? Iya dan tidak.

Solusi ini berfungsi seperti "menggeser" "roda gigi":

  • Roda gigi: ada dua <div>s. Yang satu adalah orang tua dari yang lain. Keduanya memiliki spin animasi tetapi dengan berbeda animation-duration. Status terakhir dari elemen adalah akumulasi dari kedua animasi.
  • Pergeseran: Pada awalnya, hanya satu <div> menjalankan animasinya. Yang lainnya dijeda. Saat kotak centang diaktifkan, kedua animasi menukar statusnya.

Meskipun saya sangat menyukai hasilnya, ada satu masalah: ini adalah eksploitasi yang bagus dari spin animasi, yang tidak berfungsi untuk jenis animasi lain pada umumnya.

Solusi Praktis (dengan JS)

Untuk animasi umum, dimungkinkan untuk mencapai fungsi gerakan lambat dengan sedikit JavaScript:

Penjelasan singkat:

  • Properti kustom digunakan untuk melacak kemajuan animasi.
  • Animasi "dimulai ulang" ketika kotak centang diaktifkan.
  • Kode JS menghitung yang benar animation-delay untuk memastikan transisi yang mulus. saya merekomendasi artikel ini jika Anda tidak terbiasa dengan nilai negatif dari animation-delay.

Anda dapat melihat solusi ini sebagai campuran dari "menghidupkan ulang animasi" dan pendekatan "penggeseran gigi".

Di sini penting untuk melacak kemajuan animasi dengan benar. Solusi dapat dilakukan jika @property tidak tersedia. Sebagai contoh, versi ini menggunakan z-index untuk melacak kemajuan:

Catatan samping: awalnya, saya juga mencoba membuat versi khusus CSS tetapi tidak berhasil. Meskipun tidak 100% yakin, saya pikir itu karena animation-delay is tidak bisa dianimasikan.

Ini adalah versi dengan JavaScript minimal. Hanya "memasuki slowmo" yang berfungsi.

Beri tahu saya jika Anda berhasil membuat versi khusus CSS yang berfungsi!

Slow-mo Any Animation (dengan JS)

Terakhir, saya ingin membagikan solusi yang berfungsi untuk (hampir) animasi apa pun, bahkan dengan banyak yang rumit @keyframes:

Pada dasarnya, Anda perlu menambahkan pelacak kemajuan animasi, lalu hitung dengan cermat animation-delay untuk animasi baru. Namun, terkadang sulit (tetapi mungkin) untuk mendapatkan nilai yang benar.

Sebagai contoh:

  • animation-timing-function tidak linear.
  • animation-direction tidak normal.
  • beberapa nilai dalam animation-name dengan berbeda animation-durationdan animation-delay'S.

Metode ini juga dijelaskan di sini untuk API Animasi Web.

Ucapan Terima Kasih

Saya memulai jalan ini setelah menemukan proyek khusus CSS. Beberapa adalah karya seni yang halus, dan beberapa adalah alat yang rumit. Favorit saya adalah yang melibatkan objek 3D, misalnya, ini bola memantul dan ini kubus pengepakan.

Pada awalnya, saya tidak tahu bagaimana ini dibuat. Kemudian saya membaca dan belajar banyak dari tutorial bagus ini oleh Ana Tudor.

Ternyata, membangun dan menganimasikan objek 3D dengan CSS tidak jauh berbeda dengan melakukannya dengan Pencampur, hanya dengan rasa yang sedikit berbeda.

Kesimpulan

Dalam artikel ini kami memeriksa perilaku animasi CSS saat animate-* properti diubah. Terutama kami menemukan solusi untuk "memutar ulang animasi" dan "animasi slow-mo".

Saya harap Anda menemukan artikel ini menarik. Ceritakan apa yang sedang kau pikirkan!

Stempel Waktu:

Lebih dari Trik CSS