Vue自定义封装音频播放组件(带拖拽进度条)(改版)

参考别人写的组件进行的改版
原文组件链接:https://blog.csdn.net/weixin_48215380/article/details/138598853
改版之后的样式
在这里插入图片描述

<template>
  <div class="audioModule">
    <div class="left">
      <p class="audio_Name">{{ audioName }}</p>
      <div class="audio_wrap_content">
        <audio ref="audio" @play="playFunc" @pause="pauseFunc" @timeupdate="timeupdateFunc"
          @loadedmetadata="onLoadedmetadata" @ended="handleEnd">
          <source :src="audioSrc" />
        </audio>
        <div class="cudio_control_content">

          <!-- <img @click="startPlayOrPause" class="state_img" :src="audio.playing ? stopImg : playImg" alt="" /> -->
          <div class="state_time" style="marginRight:15px">{{ audio.currentTime | formatSecond }}</div>
          <div class="slider">
            <el-slider v-model="sliderTime" :show-tooltip="false" @change="onChange"></el-slider>
          </div>
          <div class="state_time" style="marginLeft:10px">{{ audio.maxTime | formatSecond }}</div>
        </div>
      </div>
    </div>
    <div class="right">
      <div class="audio_btn active_audio_hover">
        <i class="iconfont" style="transform: rotate(180deg);"  @click="advance(2)">&#xe74e;</i>
      </div>
      <div class="audio_btn" @click="startPlayOrPause" :class="{active_audio_btn:audio.playing}">
        <i class="iconfont" v-if="!audio.playing">&#xe751;</i>
        <i class="iconfont" v-else>&#xe750;</i>
      </div>
      <div class="audio_btn active_audio_hover" >
        <i class="iconfont" @click="advance(1)">&#xe74e;</i>
      </div>

    </div>
  </div>
</template>
  
<script>
function formatTime(second) {
  var secondType = typeof second;
  if (secondType === "number" || secondType === "string") {
    second = parseInt(second);

    var hours = Math.floor(second / 3600);
    second = second - hours * 3600;
    var mimute = Math.floor(second / 60);
    second = second - mimute * 60;
    // hours + ':' +
    return ("0" + mimute).slice(-2) + ":" + ("0" + second).slice(-2);
  } else {
    return "0:00:00";
  }
}
export default {
  name: "AudioPlay",
  props: {
    audioSrc: {
      type: String,
      default: '',
    },
    audioName: {
      type: String,
      default: "",
    },
  },
  data() {
    return {
      value1: 1,
      playImg: require("@/assets/images/play.png"),
      stopImg: require("@/assets/images/stop.png"),
      sliderTime: 0,
      audio: {
        maxTime: 0 /* 音频最大播放时长 */,
        currentTime: 0 /* 当前播放时长 */,
        playing: false /* 音频当前处于播放/暂停状态 */,
      },
      activeIndex:-1
    };
  },
  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.activeIndex=-1
      this.audio.playing ? this.pause() : this.play();
    },
    /* 拖动进度条,改变当前时间 value是进度条改变时的回调函数的参数 值为0~100之间,需要换算成实际时间 */
    onChange(value) {
      console.log(value, 'values');
      this.$refs.audio.currentTime = parseInt(value / 100 * this.audio.maxTime)
      // console.log(this.$refs.audio.currentTime , 'this.$refs.audio.currentTime ');
    },
    advance(index){
      this.activeIndex=index
      if(index==1){
        // 前进五秒
        let newTime=this.$refs.audio.currentTime+5
        this.$refs.audio.currentTime=newTime>this.audio.maxTime?this.audio.maxTime:newTime
       
      }
      if(index==2){
        let newTime=this.$refs.audio.currentTime-5
        this.$refs.audio.currentTime=newTime<0?0:newTime
      }
    }
  },
  filters: {
    formatSecond(second = 0) {
      return formatTime(second)
    }
  },
};
</script>
  
<style scoped lang="scss">
.audioModule {
  width: 100%;
  height: 140px;
  background: #F2F6FA;
  border-radius: 4px 4px 4px 4px;
  border: 1px solid #E1E6F0;
  display: flex;
  align-items: center;
  padding: 20px 15px;
  box-sizing: border-box;

  .left {
    width: 60%;
    height: 100%;
    // background-color: pink;

    .audio_Name {
      font-family: PingFang SC, PingFang SC;
      font-weight: 500;
      font-size: 20px;
      color: #333333;
      line-height: 23px;
      text-align: left;
      font-style: normal;
      text-transform: none;
      margin-top: 10px;
    }
  }

  .right {
    flex: 1;
    width: 0;
    height: 100%;
    // background-color: rgb(85, 159, 188);
    display: flex;
    align-items: center;
    justify-content: space-evenly;
    .audio_btn{
      width: 50px;
      height: 50px;
      border-radius: 50px;
      background-color: #FFFFFF;
      display: flex;
      align-items: center;
      justify-content: center;
      .iconfont{
        font-size: 22px;
      }
    }
    .active_audio_btn{
      color: #006EFF;
      background-color: #E3EFFF;
    }
    .active_audio_hover:hover{
      color: #006EFF;
      background-color: #E3EFFF;
    }
  }
}

.audio_wrap_content {

  width: 400px;
  height: 40px;
  // background: pink;
  // border-radius: 4px 4px 4px 4px;
  // border: 1px solid #E1E6F0;
}

.cudio_control_content {
  margin: 0 auto;
  width: 100%;
  height: 100%;
  display: flex;

  .slider {
    flex: 1
  }

  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: PingFang SC, PingFang SC;
    font-weight: 500;
    font-size: 16px;
    color: #333333;
    line-height: 19px;
    text-align: left;
    font-style: normal;
    text-transform: none;

  }
}
::v-deep .el-slider__button{
  background-color: #409EFF;
  width: 12px;
  height: 12px;
}
::v-deep .el-slider__runway{
  height: 8px;
}
</style>

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值