1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
<script lang="ts">
import { onDestroy, onMount } from 'svelte'
import { masterMuted, ambientVolume } from '@hollowdark/lib/audio/state'
interface Props {
src: string
loop?: boolean
}
let { src, loop = false }: Props = $props()
let audioEl: HTMLAudioElement | null = null
let cleanupInteractionListeners: (() => void) | null = null
onMount(async () => {
if (!audioEl) return
audioEl.volume = $ambientVolume
audioEl.muted = $masterMuted
try {
await audioEl.play()
} catch {
const start = (): void => {
audioEl?.play().catch(() => {})
}
document.addEventListener('click', start, { once: true, passive: true })
document.addEventListener('keydown', start, { once: true, passive: true })
document.addEventListener('touchstart', start, { once: true, passive: true })
cleanupInteractionListeners = () => {
document.removeEventListener('click', start)
document.removeEventListener('keydown', start)
document.removeEventListener('touchstart', start)
}
}
})
onDestroy(() => {
cleanupInteractionListeners?.()
if (audioEl) {
audioEl.pause()
}
})
$effect(() => {
if (!audioEl) return
audioEl.volume = $ambientVolume
audioEl.muted = $masterMuted
})
</script>
<audio bind:this={audioEl} {src} {loop} preload="auto"></audio>
|