Just to make fun of it: the company has changed a lot recently. The new leader has passed all the previous projects and has to do it again. B: well… (Many, many words omitted here)

Today I want to share vue+Element rewrite audio player style, because the default player style is very ugly, UI colleagues must follow the UI.

Segmentfault.com/a/119000001…

Let’s look at the directory structure first

You have to install it in advance

yarn add element-ui // or npm i element-ui -S
Copy the code

Import and use in main.js file

// filename: src/main.js
import Vue from 'vue'
import ElementUI from 'element-ui'
import App from './App'
import 'element-ui/lib/theme-chalk/index.css'

Vue.config.productionTip = false

Vue.use(ElementUI)

/* eslint-disable no-new */
new Vue({
  el: '#app',
  template: '<App/>',
  components: { App }
})
Copy the code

Now let’s look at the audiocom.vue file

<template>
  <div>
    <audio src="http://devtest.qiniudn.com/secret base~.mp3" controls="controls"></audio>
  </div>
</template>

<script>
export default {
  data () {
    return {}
  }
}
</script>

<style>

</style>
Copy the code

We need a button to play and pause the audio, and here we call two apis of Audio, and two events.

  • audio.play()
  • audio.pause()
  • Play events
  • Pause event

Audio playback pause control

Methods: {// Control audio playback and pausestartPlayOrPause () {
      returnthis.audio.playing ? This.pause () : this.play()}, // Play the audioplay () {
      this.$refs.audio. Play ()}, // Pause the audiopause () {
      this.$refs.audio. Pause ()}, // When the audio is playingonPlay () {
      this.audio.playing = true}, // When audio pausesonPause () {
      this.audio.playing = false}}Copy the code

Audio display time

The audio time display has two main parts, the total duration of the audio and the current playing time. This can be obtained from two events

  • Loadedmetadata: The metadata representing the audio has been loaded to obtain the total duration of the audio
  • Timeupdate: The current playback position changes as part of normal playback, or in a particularly interesting way, such as discontinuously, to get the current playback time of the audio from this event, which is constantly triggered during playback

Key code: integer formatted into hours: minutes: seconds

function realFormatSecond(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

    return hours + ':' + ('0' + mimute).slice(-2) + ':' + ('0' + second).slice(-2)
  } else {
    return '0:00:00'}}Copy the code

Key code: Handling of two events

OnTimeupdate (res) {console.log('timeupdate') console.log(res) this.audio. CurrentTime = res.target.currentTime}, // When loading voice stream metadata is complete, OnLoadedmetadata (res) {console.log('loadedmetadata')
  console.log(res)
  this.audio.maxTime = parseInt(res.target.duration)
}
Copy the code

The complete code

<template>
  <div>
    <audio
      ref="audio"
      :src="url"
      @pause="onPause"
      @play="onPlay"
      @timeupdate="onTimeupdate"
      @loadedmetadata="onLoadedmetadata"
      controls="controls"></audio> <! Audio playback control --> <div class="audio-com-box">
      <div class="audio-icont-div" @click="startPlayOrPause">
        <span class="iconfont icon-shengyin"></span>
      </div>
      <div class="progress-box">
        <span class="current-time">{{ audio.currentTime | formatSecond}}</span>
        <span class="total-time"> {{audio. MaxTime | formatSecond}} < / span > < / div > < / div > < / div > < / template > < script > / / converting integers: points: second formatfunction realFormatSecond(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

    return hours + ':' + ('0' + mimute).slice(-2) + ':' + ('0' + second).slice(-2)
  } else {
    return '0:00:00'}}export default {
  data () {
    return{audio: {// This field is the playing property of whether the audio is playing:false, currentTime: 0, maxTime: 0}}}, methods: {// Control audio playback and pausestartPlayOrPause () {
      returnthis.audio.playing ? This.pause () : this.play()}, // Play the audioplay () {
      this.$refs.audio. Play ()}, // Pause the audiopause () {
      this.$refs.audio. Pause ()}, // When the audio is playingonPlay () {
      this.audio.playing = true}, // When audio pausesonPause () {
      this.audio.playing = false}, // The current playback time of the audio stream is updated when a timeUpdate event occurs approximately once per second onTimeupdate(res) {console.log('timeupdate') console.log(res) this.audio. CurrentTime = res.target.currentTime}, // When loading voice stream metadata is complete, OnLoadedmetadata (res) {console.log('loadedmetadata') console.log(res) this.audio.maxTime = parseInt(res.target.duration) } }, filters: FormatSecond (second = 0) {return realFormatSecond(second)
    }
  }
}
</script>

<style>

</style>
Copy the code

Audio progress bar control

The progress bar has two main controls. The principle for changing progress is to change the value of the audio. CurrentTime property

  • When the current time changes, the progress bar changes accordingly

  • Drag the progress bar to change the current time of audio

<el-slider
          class="slider"
          v-model="sliderTime"
          :show-tooltip="false"
          @change="changeCurrentTime"></el-slider>
Copy the code
// Drag the progress bar to change the current time. Index is the callback function parameter when the progress bar changes. It needs to be converted to the actual time changeCurrentTime(index) {this.$refs.audio. CurrentTime = parseInt(index / 100 * this.audio. MaxTime)}, OnTimeupdate (res) {console.log('timeupdate')
  console.log(res)
  this.audio.currentTime = res.target.currentTime
  this.sliderTime = parseInt(this.audio.currentTime / this.audio.maxTime * 100)
}
Copy the code

Finally fill in the full code

<template>
  <div>
    <audio
      ref="audio"
      :src="url"
      @pause="onPause"
      @play="onPlay"
      @timeupdate="onTimeupdate"
      @loadedmetadata="onLoadedmetadata"
      controls="controls"></audio> <! Audio playback control --> <div class="audio-com-box">
      <div class="audio-icont-div" @click="startPlayOrPause">
        <span class="iconfont icon-shengyin"></span>
      </div>
      <div class="progress-box">
        <el-slider
          class="slider"
          v-model="sliderTime"
          :show-tooltip="false"
          @change="changeCurrentTime"></el-slider>
        <span class="current-time">{{ audio.currentTime | formatSecond}}</span>
        <span class="total-time">{{ audio.maxTime | formatSecond}}</span>
      </div>
    </div>
  </div>
</template>
Copy the code
<script> // Convert the integer to the hour: minute: second formatfunction realFormatSecond(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
      return hours + ':' + ('0' + mimute).slice(-2) + ':' + ('0' + second).slice(-2)
    } else {
      return '0:00:00'}}export default {
    props: {},
    components: {},
    data() {
      return {
        url: 'http://final.tfedu.net/nor/3001234567890/b90e3bc71d79520d72612f00cc80832e/reading/2019/10001/7/2019071915105700931-62.m p3',
        audio: {
          playing: falseCurrentTime: 0,// maxTime: 0,// Maximum playback duration}, sliderTime: []}}, watch: {}, methods: {// Drag the progress bar to change the current time, index is the callback function when the progress bar changes parameters between 0 and 100, need to convert the actual time changeCurrentTime(index) {this.$refs.audio. CurrentTime = parseInt(index / 100 * this.audio. MaxTime)}, OnTimeupdate (res) {this.audio. CurrentTime = res.target.currentTime; this.sliderTime = parseInt(this.audio.currentTime / this.audio.maxTime * 100); }, // Control audio playback and pausestartPlayOrPause() {
        returnthis.audio.playing ? This.pause () : this.play()}, // Play the audioplay() {
        this.$refs.audio.play(); }, // Pause the audiopause() {
        this.$refs.audio.pause(); }, // When the audio playsonPlay() {
        this.audio.playing = true}, // When audio pausesonPause() {
        this.audio.playing = false}, // When the timeUpdate event is about once per second, OnTimeupdate (res) {this.audio. CurrentTime = res.target.currentTime this.sliderTime = ParseInt (this.audio. CurrentTime/this.audio. MaxTime * 100)}, OnLoadedmetadata (res) {this.audio. MaxTime = parseInt(res.target.duration)}}, Filters: {// Convert integers to time seconds formatSecond(second = 0) {return realFormatSecond(second)
      }
    },
    created() {},mounted() {
    }
  }
</script>
Copy the code
<style lang="less">
  audio {
    display: none;
  }

  .audio-com-box {
    border: 1px solid #E5E5E5;
    background-color: #FAFAFA;border-radius: 10px; padding: 15px 25px; display: flex; align-items: center; /* audio icon */ >. Audio-icont-div {width: 40px; height: 40px; border: 2px solid#17CE88;
      border-radius: 50%;
      text-align: center;
      line-height: 40px;
      cursor: pointer;
      > .icon-shengyin {
        color: #17CE88;font-size: 20px; }} /* progress bar */ >. Progress-box {flex: 1; margin-left: 15px; position: relative; > .slider { > .el-slider__runway { height: 3px; > .el-slider__bar { height: 3px; background-color:#17CE88;
          }
          .el-slider__button {
            width: 10px;
            height: 10px;
            border: 2px solid #17CE88
          }
        }
      }
      > .current-time, > .total-time {
        position: absolute;
        bottom: -15px;
        color: #AAAAAA;
      }
      > .current-time {
        left: 0;
      }
      > .total-time {
        right: 0;
      }
    }
  }
</style>

Copy the code

Segmentfault.com/a/119000001…

Or check out vue-aPlayer

(Any problems or deficiencies are welcome to correct)