vue2封装音频播放组件(带拖拽进度条)

1,123 阅读1分钟

封装的一个带拖拽进度条的音频播放组件

  • h5 audio标签
  • vant2.10.0 滑块组件
  • 字体:BIGJOHN

screenshot-20220817-140459.png

注意:暂停和播放使用的是png图片,如果需要用字体图标库或者svg自行替换

<template>
  <div class="audio_wrap" :style="[{ backgroundColor: bgColor }]">
    <audio
      ref="audio"
      @play="playFunc"
      @pause="pauseFunc"
      @timeupdate="timeupdateFunc"
      @loadedmetadata="onLoadedmetadata"
      @ended="handleEnd"
    >
      <source :src="audioSrc" />
    </audio>
    <div class="cudio_control">
      <img
        @click="startPlayOrPause"
        class="state_img"
        :src="audio.playing ? stopImg : playImg"
        alt=""
      />
      <div class="state_time" style="marginRight:5px">{{audio.currentTime | formatSecond}}</div>
      <van-slider
        v-model="sliderTime"
        bar-height="1px"
        active-color="#ffb900"
        button-size="4px"
        @change="onChange"
      >
        <template #button>
          <div class="custom-button"></div>
        </template>
      </van-slider>
      <div class="state_time" style="marginLeft:5px">{{audio.maxTime | formatSecond}}</div>
    </div>
  </div>
</template>

<script>
function formatTime(second) {
  let m = parseInt(second / 60);
  let s = parseInt(second % 60);
  let formatTime = "";
  if(second==0){
    return "0'00''"
  }
  if (m == 0) {
    if(s>=10){
      formatTime = "0'"+ s + "''";

    }else{
      formatTime = "0'0"+ s + "''";
    }
  } else {
    if(s>=10){
      formatTime = m + "'" + s + "''";
    }else{
      formatTime = m + "'0" + s + "''";
    }
  }
  return formatTime
}
export default {
  name: "AudioPlay",
  props: {
    bgColor: {
      type: String,
      default: "rgba(255,255,255,0.15)",
    },
    audioSrc: {
      type: String,
      default: require("@/assets/music/offer_des.mp3"),
    },
    themeColor: {
      type: String,
      default: "#ffb900",
    },
  },
  data() {
    return {
      playImg: require("@/assets/images/play.png"),
      stopImg: require("@/assets/images/stop.png"),
      sliderTime: 0,
      audio: {
        maxTime: 0 /* 音频最大播放时长 */,
        currentTime: 0 /* 当前播放时长 */,
        playing: false /* 音频当前处于播放/暂停状态 */,
      },
    };
  },
  methods: {
    /* 播放音频 */
    play() {
      console.log("触发 播放");
      this.$refs.audio.play();
    },
    /* 暂停音频 */
    pause() {
      this.$refs.audio.pause();
    },
    /** 当音乐播放 */
    playFunc() {
      this.audio.playing = true;
    },
    /** 当音乐暂停 */
    pauseFunc() {
      this.audio.playing = false;
    },
    /** 当音乐结束 */
    handleEnd(){
      this.sliderTime = 0
      this.audio.playing = false
      this.audio.currentTime = 0
    },
    /* 每秒触发一次 用来更新当前播放时间 */
    timeupdateFunc(res) {
      this.audio.currentTime = res.target.currentTime
      /* 当音频播放时 进度条也要随之改变 */
      this.sliderTime = parseInt(this.audio.currentTime / this.audio.maxTime * 100)
    },
    /* 音频加载完成后的回调函数 */
    onLoadedmetadata(res) {
      console.log(111);
      this.audio.maxTime = parseInt(res.target.duration);
    },
    /* 控制音频播放、暂停 */
    startPlayOrPause() {
      console.log("bof");
      this.audio.playing ? this.pause() : this.play();
    },
    /* 拖动进度条,改变当前时间 value是进度条改变时的回调函数的参数 值为0~100之间,需要换算成实际时间 */
    onChange(value){
      this.$refs.audio.currentTime = parseInt(value / 100 * this.audio.maxTime)
    }
  },
  mounted() {
    // this.play()
  },
  filters: {
    formatSecond(second=0){
      return formatTime(second)
    }
  },
};
</script>

<style scoped lang="scss">
.audio_wrap {
  // width: 180px;
  height: 26px;
  border-radius: 15px;
  // transform: translateX(-25px);
}

.cudio_control {
  margin: 0 auto;
  width: 90%;
  height: 100%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  
  .state_img {
    width: 18px;
    height: 18px;
  }

  .custom-button {
    width: 8px;
    background-color: #ffb900;
    height: 8px;
    border-radius: 8px;
  }

  .state_time {
    font-family: "BIGJOHN";
    font-size: 10px;
    color: rgba(34, 34, 34, 0.3);
    margin-right: 3px;
    margin-left: 3px;
  }
}
</style>