/** * 利用 */ import store from "@/store"; import { computed, onMounted, watch, ref, unref, reactive } from "vue"; import debounce from "lodash-es/debounce"; import mitt from "mitt"; let CLICKFIRST = false; const currentPlayer = ref(null); const isInit = ref(false); const currentAudio = computed(() => store.getters["audio/currentAudio"]); const currentAudioTemp = ref(""); const isDoneforCover = computed(() => store.getters["scene/isDoneforCover"]); const currentScene = computed(() => store.getters["scene/currentScene"]); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); const isShowCover = computed( () => store.getters["scene/metadata"].coverInfo.isShowCover === 1 || false ); async function initDefaultAudio() { watch( [isShowCover, isDoneforCover, currentScene], ([val1, val2, val3]) => { //开场完成后才开始初始化audioplayer console.log("initDefaultAudio", unref(val1), unref(val2)); if (!unref(val1)) { // 开场封面关闭时 initAudioPlayer(); } else { // 开场封面开启时并跳转完成时 if (unref(val2)) { initAudioPlayer(); } } watchUpdateCurrentScenEexplanation(unref(val3)); watchResetV4BGM(unref(val3)); }, { deep: true, immediate: true, } ); watch( currentAudio, (val) => { const oldValue = currentAudioTemp.value; const newValue = unref(val).url; const isSame = newValue === oldValue; console.log("audio-isSame", isSame); if (newValue && newValue.length > 0) { if (unref(currentPlayer)) { const url = unref(val).url; const autoplay = unref(val).isAuto; const loop = unref(val).repeat; console.log("currentAudio", unref(val).url, autoplay, loop); if (!isSame) { unref(currentPlayer).switchUrl(url, autoplay, loop); currentAudioTemp.value = newValue; } else { //相同URL的再次播放 unref(currentPlayer).resume(); } } } else { console.log('为空暂时') unref(currentPlayer) && unref(currentPlayer).stop(); } }, { deep: true, immediate: true, } ); } function initAudioPlayer() { if (!unref(isInit)) { isInit.value = true; console.log("initAudioPlayer"); const player = createAudioPlayer( unref(currentAudio).url, unref(currentAudio).isAuto, unref(currentAudio).repeat ); currentPlayer.value = player; player.on("play", () => { console.log("play--22", player.isPlaying); store.dispatch("audio/updatePlayerStatus", player.isPlaying); }); player.on("pause", () => { console.log("pause--33", player.isPlaying); store.dispatch("audio/updatePlayerStatus", player.isPlaying); }); player.on("end", () => { console.log("end--33", player._loop); store.dispatch("audio/updatePlayerStatus", player.isPlaying); }); window.store = store; } } function watchUpdateCurrentScenEexplanation(data) { if ("explanation" in data) { store.dispatch("audio/initExplanationBGM", { url: data.explanation.audioUrl, repeat: data.explanation.repeat, isAuto: data.explanation.openByDefault, }); } else { console.log("not initExplanationBGM"); store.dispatch("audio/initExplanationBGM", { url: "", repeat: false, isAuto: false, }); } } function watchResetV4BGM(data) { console.log("data.type", data.type); if (data.type !== "4dkk") { store.dispatch("audio/initV4BGM", ""); } } function createAudioPlayer(url, autoplay, loop = true) { const player = new AudioPlayer({ src: url, autoplay: autoplay, loop: loop, }); return player; } class AudioPlayer { constructor(options) { this._src = options.src; this._loop = options.loop; this._autoplay = options.autoplay || false; this._isPlaying = false; this._firstPlay = false; this._lock = false; const emitter = mitt(); Object.keys(emitter).forEach((method) => { this[method] = emitter[method]; }); this.audio = null; this.switchUrl = debounce(this.switchUrlSource, 80).bind(this); this.play = debounce(this.toPlay, 80).bind(this); this.init(); } get isPlaying() { return this._isPlaying; } switchUrlSource(url, autoplay, loop) { if ("unload" in this.audio) { console.log("switchUrlSource-1"); this.audio.unload(); } else { console.log("switchUrlSource-2"); return; } console.log("switchUrlSource", url, autoplay, loop); this._isPlaying = false; // this._lock = false; // this._firstPlay = false; this._autoplay = autoplay || false; this._loop = loop || false; this._src = url; this.audio = null; this.createAudio(); this.play(); this.emit("change", this.audio); } init() { this.createAudio(); this.bindElement(); this.play(); this.emit("ready", this.audio); } createAudio() { this.audio = new Howl({ preload: true, src: [this._src], loop: this._loop || false, html5: false, onplay: () => { this._isPlaying = true; this.emit("play"); }, onpause: () => { this._isPlaying = false; this.emit("pause"); }, onend: () => { this._isPlaying = false; console.log("onend", this._loop); if (!this._loop) { this.audio.unload(); } this.emit("end"); }, }); } bindElement() { const $player = document.querySelector(".ui-view-layout"); const onclick = () => { $player.removeEventListener("click", onclick); $player.removeEventListener("touchstart", onclick); //判断是否第一次进入或者是否已点击过 或已自动播放过。 if (CLICKFIRST || this._isPlaying) { console.log("已点击过或自动播放中"); return; } CLICKFIRST = true; this.play(); }; $player.addEventListener("click", onclick); $player.addEventListener("touchstart", onclick); } async toPlay() { try { if (!this._isPlaying && !this._lock) { // console.log("play---1", this._autoplay, this._lock, this._firstPlay); console.log( `playStatus: audioplay->${this._autoplay}, lock:${this._lock},firstPlay:${this._firstPlay},loop:${this._loop}` ); if (this._autoplay || this._firstPlay) { await this.audio.play(); } else { //默认不自动播放重置状态并记录已播放过 if (CLICKFIRST) { this._firstPlay = true; } this._isPlaying = false; store.dispatch("audio/updatePlayerStatus", false); } } } catch (error) { console.warn("playError", error); } } pause() { return this.audio.pause(); } resume() { console.log("resume"); if (!this._isPlaying) { return this.audio.play(); } } stop() { this.pause(); store.dispatch("audio/updatePlayerStatus", false); } destroy() { console.warn("audio-destroy"); if ("unload" in this.audio) { this.audio.unload(); } this._isPlaying = false; this._autoplay = false; this._loop = false; this._src = ""; this.audio = null; store.dispatch("audio/updatePlayerStatus", false); this.emit("destroy"); } lock() { console.log("audio-lock"); this._lock = true; this.pause(); } unlock() { console.log("audio-unlock"); this._lock = false; } mute() { return this.audio.mute(true); } unmute() { return this.audio.mute(false); } } export function useAudio() { return { initDefaultAudio, currentPlayer, }; }