/** * 利用 */ import store from '@/store'; import { computed, onMounted, watch, ref, unref } 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 isDoneforCover = computed(() => store.getters["scene/isDoneforCover"]); const currentScene = computed(() => store.getters["scene/currentScene"]); 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, old) => { const isSame = unref(old) && unref(val).url === unref(old).url; console.log('isSame', isSame); if (unref(val) && unref(val).url.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); } else { //相同URL的再次播放 unref(currentPlayer).resume(); } } } }, { 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.isPlaying); 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; this._isPlaying = false; this._lock = false; const emitter = mitt() Object.keys(emitter).forEach((method) => { this[method] = emitter[method] }) this.audio = null this.switchUrl = debounce(this.switchUrlSource, 300).bind(this); this.play = debounce(this.toPlay, 300).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); this._isPlaying = false; this._lock = 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 this.emit('end') }, }) } bindElement() { const $player = document.querySelector('.ui-view-layout') const onclick = () => { $player.removeEventListener('click', onclick) $player.removeEventListener('touchstart', onclick) //判断是否第一次进入或者是否已点击过 if (CLICKFIRST) { 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) if (this._autoplay) { await this.audio.play(); } else { //默认不自动播放重置状态 this._isPlaying = false store.dispatch('audio/updatePlayerStatus', false); } } } catch (error) { console.warn('playError', error); } } pause() { return this.audio.pause(); } resume() { 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() { this._lock = true } unlock() { this._lock = false } mute() { return this.audio.mute(true); } unmute() { return this.audio.mute(false); } } export function useAudio() { return { initDefaultAudio, currentPlayer, }; }