| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- /**
- * 音频播放 Pinia Store
- * 跨页面共享音频播放状态,音频实例存放在 globalData 中确保单例
- */
- import { defineStore } from 'pinia'
- const AUDIO_LIST = [
- { name: '河流', posterimg: '/static/device/heliu.png', url: '/static/audio/audio1.mp3' },
- { name: '下雨', posterimg: '/static/device/heliu.png', url: '/static/audio/audio2.mp3' }
- ]
- // 通过 globalData 确保 InnerAudioContext 跨页面单例
- function _getAudioCtx() {
- const app = getApp()
- if (!app.globalData) app.globalData = {}
- return app.globalData._audioContext || null
- }
- function _setAudioCtx(ctx) {
- const app = getApp()
- if (!app.globalData) app.globalData = {}
- app.globalData._audioContext = ctx
- }
- export const useAudioStore = defineStore('audio', {
- state: () => ({
- audiolist: AUDIO_LIST,
- curAudioInx: 0,
- totalTime: 0,
- currentTime: 0,
- ispause: true, // true=暂停中, false=播放中
- isShowDrawer3: false
- }),
- actions: {
- /** 初始化或恢复音频上下文(页面进入时调用) */
- initAudio() {
- let ctx = _getAudioCtx()
- if (ctx) {
- // 已有实例,重新绑定事件监听
- this._bindEvents(ctx)
- // 同步当前播放状态
- if (!ctx.paused && ctx.src) {
- this.ispause = false
- this.currentTime = ctx.currentTime || 0
- this.totalTime = ctx.duration || 0
- }
- return
- }
- // 首次创建
- ctx = uni.createInnerAudioContext()
- ctx.src = this.audiolist[this.curAudioInx].url
- ctx.loop = true
- _setAudioCtx(ctx)
- this._bindEvents(ctx)
- },
- /** 绑定事件监听 */
- _bindEvents(ctx) {
- // 先清除旧监听,避免重复绑定(部分平台新建ctx调用off会报错,需保护)
- try {
- ctx.offPlay && ctx.offPlay()
- ctx.offCanplay && ctx.offCanplay()
- ctx.offError && ctx.offError()
- ctx.offTimeUpdate && ctx.offTimeUpdate()
- ctx.offPause && ctx.offPause()
- ctx.offStop && ctx.offStop()
- } catch (e) {
- // 忽略:新创建的ctx可能没有已注册的监听器
- }
- ctx.onPlay(() => {
- this.totalTime = ctx.duration || 0
- this.ispause = false
- })
- ctx.onCanplay(() => {
- this.totalTime = ctx.duration || 0
- })
- ctx.onError((res) => {
- console.log('播放错误', res.errMsg)
- })
- ctx.onTimeUpdate(() => {
- this.currentTime = ctx.currentTime || 0
- })
- ctx.onPause(() => {
- this.ispause = true
- })
- ctx.onStop(() => {
- this.ispause = true
- this.currentTime = 0
- })
- },
- /** 页面离开时解绑事件(不销毁音频) */
- detachEvents() {
- const ctx = _getAudioCtx()
- if (ctx) {
- try {
- ctx.offPlay && ctx.offPlay()
- ctx.offCanplay && ctx.offCanplay()
- ctx.offError && ctx.offError()
- ctx.offTimeUpdate && ctx.offTimeUpdate()
- ctx.offPause && ctx.offPause()
- ctx.offStop && ctx.offStop()
- } catch (e) {
- // 忽略
- }
- }
- },
- /** 切换播放/暂停 */
- playAudio() {
- const ctx = _getAudioCtx()
- if (!ctx) return
- if (this.ispause) {
- ctx.play()
- } else {
- ctx.pause()
- }
- },
- /** 切换音源(切换后主动播放) */
- changeAudio(url, inx) {
- this.curAudioInx = inx
- this.ispause = false
- const ctx = _getAudioCtx()
- if (ctx) {
- ctx.stop()
- setTimeout(() => {
- ctx.src = url
- ctx.play()
- }, 300)
- } else {
- // 音频上下文不存在时,先初始化再播放
- this.initAudio()
- const newCtx = _getAudioCtx()
- if (newCtx) {
- newCtx.src = url
- newCtx.play()
- }
- }
- },
- /** 停止播放(模式切换时调用) */
- stopAudio() {
- const ctx = _getAudioCtx()
- if (ctx) {
- ctx.stop()
- }
- this.ispause = true
- this.currentTime = 0
- },
- /** 彻底销毁音频(APP退出等极端场景) */
- destroyAudio() {
- const ctx = _getAudioCtx()
- if (ctx) {
- ctx.stop()
- ctx.destroy()
- _setAudioCtx(null)
- }
- this.ispause = true
- this.currentTime = 0
- this.totalTime = 0
- },
- /** 格式化时间 */
- formatTime(totalSeconds) {
- totalSeconds = Math.floor(totalSeconds || 0)
- const minutes = Math.floor(totalSeconds / 60)
- const seconds = totalSeconds % 60
- return minutes.toString().padStart(2, '0') + ':' + seconds.toString().padStart(2, '0')
- }
- }
- })
|