音乐播放暂停

audio-util.js

import { Howl } from "howler";

const audioUtil = {
  audioArr: [],
  soundControl: {},
  currentAudioId: "",
  currentAudioIconDom: "",
  isPageHide: false,


  /**
   * @description: 初始化音频
   * @return {*}
   * @param {*} audioArr [{id: '', url: '', dom: ''}]
   */
  init(audioArr = []) {
    this.audioArr = audioArr;
    audioArr.forEach((item) => {
      const { id, url, dom } = item;
      if (!id || !url) return;
      this.soundControl[id] = new Howl({
        src: url.replace('http://', 'https://'), // TODO 优化
        preload: true,
        loop: false,
        autoplay: false,
        html5: true, // TODO ios 设 true, android 设 false
        volume: 1
      });
      this.soundControl[id].on('play', () => {
        this.singleAudioIconPlay(dom);
        // EventBus.$emit('audio-play', this.currentAudioId); // TODO 通知
      });
      this.soundControl[id].on('end', () => {
        this.allAudioIconPause();
        // EventBus.$emit('audio-end', this.currentAudioId); // TODO 通知
      });
    });
    document.addEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
    console.log('audioUtil - init', new Date().getTime(), this.soundControl);
  },

  /**
   * @description: 播放或暂停音乐
   * @return {*}
   * @param {*} audioId
   */
  playOrPauseAudio(audioId) {
    if (!audioId) return;

    const audioInfo = this.audioArr.filter((item) => item.id === audioId)[0];
    if (!audioInfo) return;

    const { dom: audioIconDom } = audioInfo;

    // 点击同一音频
    if (audioId === this.currentAudioId && this.soundControl[audioId]) {
      if (this.soundControl[audioId].playing()) {
        // 播放中要暂停
        this.soundControl[audioId].pause();
        this.allAudioIconPause();
      } else {
        // 暂停中要播放
        this.soundControl[audioId].play();
        this.singleAudioIconPlay(audioIconDom);
      }
      return;
    }

    // 点击不同音频
    this.pauseAudio();
    if (!this.soundControl[audioId]) return;
    this.soundControl[audioId].stop();
    this.soundControl[audioId].play();
    this.singleAudioIconPlay(audioIconDom);

    // 保存变量
    this.currentAudioId = audioId;
    this.currentAudioIconDom = audioIconDom;
  },

  // 暂停音频
  pauseAudio() {
    if (this.soundControl[this.currentAudioId]) {
      this.soundControl[this.currentAudioId].pause();
      this.allAudioIconPause();
    }
  },

  // 所有音频按钮置为暂停要播放状态 ⏹️
  allAudioIconPause() {
    const doms = document.querySelectorAll(".audio-status-icon");
    [...doms].forEach((item) => {
      item.setAttribute("class", "audio-status-icon play");
    });
  },

  // 当前音频按钮置为播放要暂停状态 ⏸️
  singleAudioIconPlay(dom) {
    if (!dom) return;
    dom.setAttribute("class", "audio-status-icon pause");
  },

  // 处理页面切后台逻辑
  handleVisibilityChange() {
    // 隐藏,暂停
    if (window.document.hidden) {
      if (
        this.soundControl
        && this.soundControl[this.currentAudioId]
        && this.soundControl[this.currentAudioId].playing()
      ) {
        this.isPageHide = true;
        this.soundControl[this.currentAudioId].pause();
        this.allAudioIconPause();
      }
    }
    // 显示,播放
    if (!window.document.hidden) {
      if (
        this.isPageHide
        && this.soundControl
        && this.soundControl[this.currentAudioId]
      ) {
        this.isPageHide = false;
        this.soundControl[this.currentAudioId].play();
        this.singleAudioIconPlay(this.currentAudioIconDom);
      }
    }
  },

  // 销毁清除控制器
  destroy() {
    document.removeEventListener('visibilitychange', this.handleVisibilityChange.bind(this));
    if (this.soundControl) {
      this.soundControl = null;
    }
  },
};

export default audioUtil;

demo

// 1、如果按钮状态切换失败,先确定 audioIconDom 是否存在;
// 2、播放事件 dom 和播放状态 icon 可分离,注意播放事件的第二个参数和 ref 对应即可;

import audioUtil from 'audio-util';

// html
<div
  class="audio-status-icon play"
  ref="audioId"
  @click.stop="playCurrentAudio(audioId)"
></div>

// css
.audio-status-icon {
  &.play {}
  &.pause {}
}

// js
audioUtil.init([{
  id: 'audio1',
  url: '',
  dom: this.$refs['audio1'] || null
}, {
  id: 'audio2',
  url: '',
  dom: this.$refs['audio2'] || null
}]);

playCurrentAudio(audioId) {
  audioUtil.playOrPauseAudio(audioId);
}

audioUtil.destroy();