Galeri Foto Mosaik Mengalir Tanpa Ujung
Menampilkan 25 foto momen bahagia dalam susunan kotak mosaik yang terus bergulir halus otomatis ke bawah tanpa terputus, dan tetap bisa digeser manual.
Menampilkan 25 foto momen bahagia dalam susunan kotak mosaik yang terus bergulir halus otomatis ke bawah tanpa terputus, dan tetap bisa digeser manual.
Tantangan & Kebutuhan Pengguna
Menampilkan 25 foto pre-wedding dalam daftar vertikal standar membuat halaman galeri terasa monoton dan memiliki ujung bawah yang menghentikan eksplorasi visual. Pustaka carousel pihak ketiga umumnya dirancang untuk slide berdimensi seragam, sehingga gagal ketika harus merender tata letak Bento Grid asimetris (kombinasi kotak besar 2×2, potret tinggi 1×2, dan persegi 1×1) yang harus berjalan otomatis secara halus sekaligus mengizinkan intervensi gulir jari pengguna kapan saja.
Ilusi ruang tanpa batas tercipta dari tiga salinan identik: selama titik pandang pengguna dijaga tetap di salinan tengah, tepi atas dan bawah tidak akan pernah tersentuh.
Solusi & Cara Kerja
Komponen `GallerySwiper` memetakan 25 foto ke dalam matriks deterministik `PLACEMENTS` berukuran 3 kolom × 15 baris (`ROW_UNIT = 130px`, `GAP = 4px`) dengan tinggi satu blok utuh `SINGLE_HEIGHT`. DOM kemudian merender tiga salinan identik secara berurutan (`copy-a`, `copy-b`, `copy-c`) dan menginisialisasi `scrollTop` tepat di awal salinan kedua (`copy-b`). Sebuah loop `requestAnimationFrame` menghitung selisih waktu antar-frame (`dt`) untuk menggeser posisi gulir sebesar 38 piksel/detik, sementara listener `onScroll` memantau guliran manual pengguna dan melompatkan posisi `±SINGLE_HEIGHT` secara tak kasatmata setiap kali melewati ambang batas.
Berikut adalah implementasi perhitungan dimensi blok, loop animasi berbasis delta-time, dan sinkronisasi gulir manual dari `src/components/GallerySwiper.tsx`:
Detail & Hal yang Diperhatikan
- Konsistensi kecepatan lintas refresh-rate: Penggunaan delta-time `dt = (ts - lastTimeRef.current) / 1000` menjamin laju gulir tetap 38 px/detik baik pada layar ponsel 60Hz maupun 120Hz ProMotion.
- Sinkronisasi auto-scroll dengan manual flick: `posRef.current` wajib langsung diperbarui di dalam handler `onScroll` agar frame `requestAnimationFrame` berikutnya tidak menarik kembali posisi scroll ke koordinat lama yang memicu efek jitter.
- Pemetaan matriks bebas celah: Konstanta `PLACEMENTS` berisi tuple `[colStart, rowStart, colSpan, rowSpan]` yang dihitung secara presisi untuk 25 foto sehingga sambungan antara baris ke-15 pada `copy-a` dan baris ke-1 pada `copy-b` menyatu sempurna.