Efek Tirai Hitam Penutup Layar Saat Ganti Halaman
Tirai hitam elegan menutup dan membuka layar secara mulus saat tamu berpindah dari undangan utama menuju halaman galeri foto, tanpa kedipan putih.
Tirai hitam elegan menutup dan membuka layar secara mulus saat tamu berpindah dari undangan utama menuju halaman galeri foto, tanpa kedipan putih.
Tantangan & Kebutuhan Pengguna
Saat pengguna menekan tombol 'Lihat Galeri Foto' untuk berpindah dari rute '/' ke '/gallery', navigasi standar Next.js akan langsung mengganti pohon komponen halaman. Jika animasi transisi diletakkan di dalam state komponen halaman asal, animasi tersebut akan terputus di tengah jalan ketika halaman asal di-unmount, menyebabkan kedipan visual (flash) yang merusak suasana sinematik.
Elemen transisi antar-halaman harus hidup di luar siklus hidup komponen halaman yang sedang digantikannya.
Solusi & Cara Kerja
Hook usePageTransition di dalam app/components/PageTransition.tsx menggunakan pendekatan imperatif: menyuntikkan elemen kontainer #__ptc dan tag <style id='__ptc-style'> langsung ke document.body dan document.head. Ketika fungsi navigate(href) dipanggil, tirai segera menutup layar (class 'in'), menjalankan animasi bar progres hingga 75%, lalu memanggil router.push(href). Sembari menunggu Next.js memuat halaman tujuan, sebuah loop requestAnimationFrame (checkReady) memeriksa apakah waktu minimum 600ms telah berlalu dan window.location.pathname telah berubah menjadi href. Begitu terpenuhi, bar progres dipercepat menuju 100% dan tirai memudar keluar (class 'out').
Berikut adalah implementasi injeksi tirai dan sinkronisasi kesiapan rute dari file app/components/PageTransition.tsx:
Detail & Hal yang Diperhatikan
- Pencegahan Kedipan Cepat (Minimum Display Guarantee): Jika aset rute tujuan sudah berada di cache browser, perpindahan URL bisa selesai dalam hitungan milidetik. Syarat elapsed > 600 menjamin tirai transisi tetap tampil anggun selama minimal 0.6 detik.
- Pengaman Anti-Freeze (3s Timeout Guard): Apabila jaringan lambat atau navigasi gagal, batas waktu elapsed > 3000 memastikan tirai selalu dibuka kembali sehingga antarmuka pengguna tidak pernah terkunci permanen.
- Singleton DOM Reuse: Fungsi injectStyles() dan createCurtain() memeriksa keberadaan ID elemen terlebih dahulu agar navigasi berulang tidak menduplikasi node di dalam document.body.
Saat tirai berada dalam status 'out', properti CSS pointer-events: none diterapkan secara otomatis agar elemen #__ptc yang memiliki z-index: 9999 tidak menghalangi klik pada halaman baru.