自定义audio组件

先看下效果图

<template>
  <div class="musicPlay" v-if="audioVisible">
    <!-- ref="audio" -->
    <audio
      ref="audio"
      id="course-aud"
      @play="playFunc"
      @pause="pauseFunc"
      @timeupdate="timeupdateFunc"
      @canplay="canplayFunc"
      @error="errorFunc"
      :src="audioSrc"
    >
    </audio>
    <div class="audioControl">
      <div class="errorMask" v-show="isError">{{ errorMsg }}</div>
      <p class="audioClose" @click="audioVisible = false">x</p>
      <p>{{ customerName }}</p>
      <div
        style="display: flex; align-items: center"
        @mousedown="isDraging = true"
        @mouseup="isDraging = false"
      >
        <el-slider
          v-model="playProcess"
          class="sliderClass"
          style="width: 80%"
          @change="setProcessFunc"
          :format-tooltip="formatTooltip"
        ></el-slider>
        <div style="color: #333; width: 120px; text-align: right">
          {{ formatCurrentTime }} / {{ formatDuration }}
        </div>
      </div>
      <div class="playControl">
        <span
          class="audioSpan"
          @click="clickFunc('play')"
          v-show="!isPlaying"
          style="width: 10px"
          ><i class="el-icon-video-play" aria-hidden="true"></i
        ></span>
        <span
          class="audioSpan"
          @click="clickFunc('pause')"
          v-show="isPlaying"
          style="width: 10px"
          ><i class="el-icon-video-pause" aria-hidden="true"></i
        ></span>
        <span
          class="audioSpan"
          @click="clickFunc('backward')"
          style="width: 10px;margin-right: 15px;"
          ><i class="el-icon-d-arrow-left" aria-hidden="true"></i
        ></span>
        <span class="audioSpan" style="margin-right: 10px;">
          <span class="speed">X {{ playSpeed | fmtPlaySpeed() }}</span>
        </span>
        <span
          class="audioSpan"
          @click="clickFunc('forward')"
          style="width: 10px"
          ><i class="el-icon-d-arrow-right" aria-hidden="true"></i
        ></span>
        <!-- <span
          class="audioSpan"
          @click="clickFunc('refresh')"
          style="width: 10px"
          ><i class="el-icon-refresh" aria-hidden="true"></i
        ></span> -->
        <!-- <span class="audioVolSpan" style="width: 10px"
          ><i class="el-icon-microphone" aria-hidden="true"></i
        ></span> -->
        <!-- <el-slider
          v-model="playVolume"
          class="sliderVolumClass"
          :format-tooltip="formatTooltipVol"
          @change="setVolumeFunc"
        ></el-slider> -->
      </div>
    </div>
  </div>
</template>
<script>
// import { mapState } from "vuex";
function toStringFunc (param) {
  if (param > 9) {
    return param + ''
  } else {
    return '0' + param
  }
}
export default {
  name: 'CustomAudio',
  props: {
    customerName: {
      type: String,
      default: ''
    }, // 父组件传递过来的音频名称
    audioSrc: {
      type: String,
      default: ''
    }, // 父组件传递的音频链接
    audioVisible: {
      type: Boolean,
      default: false
    } // 控制音频组件的显示与隐藏
  },
  data () {
    return {
      musicUrl: '',
      isPlaying: false,
      isError: false,
      src: '',
      playProcess: 0,
      playVolume: 50,
      playSpeed: 1,
      totalTimes: '00:00',
      currentTime: '00:00',
      errorMsg: '音频加载失败,无法播放!',
      isDraging: false
    }
  },
  watch: {
    audioSrc (nVal, oVal) {
      this.src = nVal
    }
  },
  filters: {
    fmtPlaySpeed (pSpeed) {
      return pSpeed.toFixed(1)
    }
  },
  computed: {
    formatDuration () {
      if (typeof this.totalTimes === 'number') {
        const fTotal = Math.floor(this.totalTimes)
        const tempMin = Math.floor(fTotal / 60)
        const tempSec = fTotal % 60
        // const min, sec
        return `${toStringFunc(tempMin)} : ${toStringFunc(tempSec)}`
      }
      return '00:00'
    },
    formatCurrentTime () {
      if (typeof this.currentTime === 'number') {
        const fTotal = Math.floor(this.currentTime)
        const tempMin = Math.floor(fTotal / 60)
        const tempSec = fTotal % 60
        // const min, sec;
        return `${toStringFunc(tempMin)} : ${toStringFunc(tempSec)}`
      }
      return '00:00'
    }
  },
  methods: {
    load () {
      this.$refs.audio.load()
    },
    play () {
      this.$refs.audio.play()
    },
    pause () {
      this.$refs.audio.pause()
    },
    mousedownFunc () {
      this.isDraging = true
    },
    mouseupFunc () {
      this.isDraging = false
    },
    formatTooltip (val) {
      const currTime = Math.floor((val / 100) * this.totalTimes)
      const tempMin = Math.floor(currTime / 60)
      const tempSec = currTime % 60
      // const min, sec;
      return `${toStringFunc(tempMin)} : ${toStringFunc(tempSec)}`
    },
    formatTooltipVol (vol) {
      return Math.round(((vol * 2) / 100) * 10) / 10
    },
    clickFunc (val) {
      if (val === 'play') {
        this.isPlaying = !this.isPlaying
        this.$refs.audio.play()
      } else if (val === 'pause') {
        this.isPlaying = !this.isPlaying
        this.$refs.audio.pause()
      } else if (val === 'backward') {
        // 加快音频播放速度,速率范围[0.5,2]
        if (this.playSpeed > 0.5) {
          this.playSpeed -= 0.5
          this.$refs.audio.playbackRate = this.playSpeed
        }
      } else if (val === 'forward') {
        // 减慢音频播放速度,速率范围[0.5,2]
        if (this.playSpeed < 2) {
          this.playSpeed += 0.5
          this.$refs.audio.playbackRate = this.playSpeed
        }
      } else if (val === 'refresh') {
        this.$refs.audio.playbackRate = 1
        this.playSpeed = 1
        this.$refs.audio.load()
        this.$refs.audio.play()
      }
    },
    setProcessFunc (val) {
      this.$refs.audio.currentTime = Math.round((val / 100) * this.totalTimes)
      this.$refs.audio.play()
    },
    setVolumeFunc (vol) {
      // 设置播放音量,audio音量范围[0,1]
      this.$refs.audio.volume = Math.round((vol / 100) * 10) / 10
    },
    playFunc (e) {
      // console.log('music is playing')
      this.isPlaying = true
      this.$emit('play', this.isPlaying)
    },
    pauseFunc (e) {
      // console.log('music is paused')
      this.isPlaying = false
      this.$emit('pause', this.isPlaying)
    },
    timeupdateFunc (e) {
      if (!this.isDraging) {
        this.playProcess = (e.target.currentTime / this.totalTimes) * 100
        this.currentTime = e.target.currentTime
      }
      this.$emit('timeupdate', this.currentTime, this.playProcess)
    },
    canplayFunc (e) {
      // console.log('music can be played')
      this.isError = false
      this.$refs.audio.volume = 0.5
      this.totalTimes = e.target.duration // 无
      console.log(e.target.duration, 'duration')
    },
    errorFunc (e) {
      // console.log('music load error!')
      this.isError = true
    }
  }
}
</script>
<style scoped lang="less">
::v-deep .el-slider__runway {
  height: 4px;
  .el-slider__bar {
    height: 4px;
  }
}
::v-deep.el-slider__button-wrapper {
  height: 20px;
  width: 20px;
  top: -10px;
  .el-slider__button {
    width: 12px !important;
    height: 12px !important;
  }
}
.musicPlay {
  display: flex;
  // justify-content: center;
  // margin-bottom: 400px;
  // .sliderClass,
  // .audioControl {
  //   position: relative;
  // }

  .audioControl {
    // position: fixed;
    // left: 15%;
    // bottom: 0%;
    width: 700px;
    height: 80px;
    border-radius: 50px;
    padding: 0 50px;
    background-color: #f2f2f2;
    .errorMask {
      color: #e6a23c;
      text-align: center;
      width: 100%;
      height: 100%;
      position: absolute;
      top: 0;
      left: 0;
      z-index: 999;
    }
    .audioClose{
        position: absolute;
        top:-10%;
        right: 3%;
        font-size: 25px;
    }
    p {
      color: #333;
      margin: 12px 0 0 0;
    }
    .playControl {
      display: flex;
      align-items: center;
      user-select: none;
      // margin-top: 5px;

      .audioSpan,
      .audioVolSpan {
        color: #333;
        font-size: 20px;
        margin-right: 30px;
        cursor: pointer;
        &:hover {
          color: #999;
        }
        .audioIcon {
          font-size: 28px;
        }
        .speed {
          font-size: 16px;
        }
        .volume {
          font-size: 18px;
        }
      }
      .audioVolSpan {
        margin-right: 10px;
        margin-left: 32%;
      }
      .sliderVolumClass {
        display: inline-block;
        width: 25%;
        .el-slider__runway {
          margin: 0;
        }
      }
    }
  }
}
/deep/.el-slider__button {
  border:  2px solid #333;
}
/deep/.el-slider__bar {
  background: #333;
}
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值