fix(assets): use audio context instead of cloning HTMLAudioElement

This commit is contained in:
2026-02-26 11:21:23 +01:00
parent 6995cde01f
commit 02e00b170a

View File

@@ -7,24 +7,45 @@ type Rect = [number, number, number, number];
let atlasImage: HTMLImageElement | null = null; let atlasImage: HTMLImageElement | null = null;
const modelCache = new Map<string, THREE.Group>(); const modelCache = new Map<string, THREE.Group>();
const createAudio = (path: string) => { const audioContext = import.meta.client ? new AudioContext() : null;
const source = import.meta.client ? new Audio(path) : null;
return {
play: (volume = 1) => {
if (!source) return;
const app = useAppStore();
const audio = source.cloneNode() as HTMLAudioElement;
audio.volume = Math.min(1, volume * app.settings.volume);
audio.addEventListener("ended", () => audio.remove(), { once: true });
audio.play().catch(() => {});
},
};
};
const loaded = ref(0); const loaded = ref(0);
const total = ref({{TOTAL}}); const total = ref({{TOTAL}});
const isReady = computed(() => loaded.value === total.value); const isReady = computed(() => loaded.value === total.value);
const createAudio = (path: string) => {
let buffer: AudioBuffer | null = null;
if (audioContext) {
total.value += 1;
fetch(path)
.then((r) => r.arrayBuffer())
.then((buf) => audioContext.decodeAudioData(buf))
.then((buf) => {
buffer = buf;
loaded.value += 1;
})
.catch(() => {
loaded.value += 1;
});
}
return {
play: (volume = 1) => {
if (!audioContext || !buffer) return;
const app = useAppStore();
const gain = audioContext.createGain();
gain.gain.value = Math.min(1, volume * app.settings.volume);
const node = audioContext.createBufferSource();
node.buffer = buffer;
node.connect(gain).connect(audioContext.destination);
node.start();
},
};
};
if (import.meta.client) { if (import.meta.client) {
atlasImage = document.createElement('img'); atlasImage = document.createElement('img');
atlasImage.src = '/nds/atlas.webp?v={{ATLAS_HASH}}'; atlasImage.src = '/nds/atlas.webp?v={{ATLAS_HASH}}';