Pemutar Musik Global Lintas Rute
Komponen audio latar yang dipasang di tingkat RootLayout sehingga lagu tidak terputus atau mengulang dari awal ketika pengguna berpindah halaman.
Membaca sekitar 1 menit
Komponen audio latar yang dipasang di tingkat RootLayout sehingga lagu tidak terputus atau mengulang dari awal ketika pengguna berpindah halaman.
MusicPlayer menyiapkan objek Audio('/backsound.mp3') di awal dan mendengarkan event 'wedding:play' yang ditembakkan saat tombol Buka Undangan ditekan.
Menjaga suasana emosional tetap utuh saat tamu berpindah dari adegan penutup menuju halaman galeri foto dan kembali lagi.
Masalahnya dulu
Ada dua rintangan besar saat memasang musik latar di aplikasi web modern: pertama, semua browser memblokir pemutaran audio otomatis (autoplay) sebelum ada interaksi pengguna; kedua, jika pemutar musik ditaruh di dalam halaman utama (app/page.tsx), musik akan mati mendadak saat tamu berpindah ke halaman Galeri (app/gallery/page.tsx).
Arsitektur audio di tingkat RootLayout
Untuk mengatasi masalah kedua, komponen MusicPlayer diletakkan langsung di dalam app/layout.tsx berdampingan dengan {children}. Karena RootLayout di Next.js App Router tidak di-unmount saat navigasi antar-halaman, objek HTMLAudioElement tetap hidup dan terus berputar mulus.
Menaruh pemutar audio di RootLayout dan memicunya lewat CustomEvent dari tombol sampul adalah cara paling bersih menaklukkan kebijakan autoplay browser.
Implementasi di ngodingan ini
Begitu tamu menekan tombol 'Buka Undangan' di komponen Opening, sebuah event global 'wedding:play' ditembakkan. MusicPlayer menangkap event tersebut tepat di dalam siklus interaksi klik pengguna sehingga pemutaran audio diizinkan penuh oleh browser:
// Di komponen Opening saat tombol diklik:
const handleOpen = () => {
setStage(3);
window.dispatchEvent(new Event("wedding:play"));
setTimeout(onOpen, 900);
};
// Di komponen MusicPlayer (app/components/MusicPlayer.tsx):
useEffect(() => {
const handler = () => {
const a = audioRef.current;
if (a && !playing) {
a.play()
.then(() => setPlaying(true))
.catch(() => {});
}
};
window.addEventListener("wedding:play", handler);
return () => window.removeEventListener("wedding:play", handler);
}, [playing]);Jebakan dan detail yang harus dijaga
- Volume awal diatur pada angka lembut 0.35 (a.volume = 0.35) dengan loop = true agar musik latar tidak mengagetkan pengguna yang sedang memakai earphone.
- Tombol mengambang di pojok kanan bawah memantau event 'canplaythrough' sebelum mengaktifkan state ready, sehingga pengguna tidak menekan tombol play saat berkas MP3 belum siap diputar.
- Membersihkan sumber audio (a.pause(); a.src = '') pada fungsi cleanup useEffect untuk mencegah kebocoran memori atau suara ganda saat pengembangan dengan Hot Module Replacement (HMR).
Ringkasnya
Dengan menggabungkan persistensi RootLayout dan komunikasi berbasis event, musik latar berjalan tanpa hambatan di seluruh halaman aplikasi.