【vue】【audio】audio标签播放样式改写

在这里插入图片描述

<template>
  <div class="app-audio-player">
    <van-icon
      class="voice-btn"
      size="2rem"
      color="#fff"
      :name="isPlay ? 'pause-circle-o' : 'play-circle-o'"
      @touchstart="startPlayOrPause"
    />

    <div class="time">
      <span class="start-time">{{ audio.currentTime | realFormatSecond }}</span>
      <span>/</span>
      <span class="end-time">{{ audio.maxTime | realFormatSecond }}</span>
    </div>
    <div
      class="slider"
      @touchstart="progressHandleTouch('start', $event)"
      @touchmove="progressHandleTouch('move', $event)"
      @touchend="progressHandleTouch('end', $event)"
    >
      <div class="slider-track"></div>
      <div class="slider-fill" :style="'width:' + sliderTime + '%'"></div>
    </div>
    <audio
      ref="audio"
      style="display: none"
      :src="data && data.filePath"
      controls="controls"
      @pause="onPause"
      @play="onPlay"
      @timeupdate="onTimeupdate"
      @loadedmetadata="onLoadedmetadata"
    ></audio>
  </div>
</template>

<script>
export default {
  props: {
    data: {
      type: Object,
      default() {
        return {};
      },
    },
  },
  data() {
    return {
      isPlay: false, // 播放暂停按钮
      sliderTime: 0,
      silderNone: 0,
      audio: {
        // 该字段是音频是否处于播放状态的属性
        playing: false,
        // 音频当前播放时长
        currentTime: 0,
        // 音频最大播放时长
        maxTime: 0.0,
        minTime: 0,
        step: 0.1,
      },
    };
  },
  mounted() {},
  methods: {
    /**
     * 控制音频的播放与暂停
     */
    startPlayOrPause() {
      if (!(this.data && this.data.filePath)) {
        return;
      }
      if (!this.audio.playing) {
        this.$refs.audio.play();
      } else {
        this.$refs.audio.pause();
      }
    },
    // 当音频播放
    onPlay() {
      this.audio.playing = true;
      this.isPlay = true;
      this.$emit('playAudio', this.isPlay);
    },
    // 当音频暂停
    onPause() {
      this.audio.playing = false;
      const startTime = parseInt(this.audio.currentTime);
      this.isPlay = false;
      if (startTime === this.audio.maxTime) {
        this.sliderTime = 0;
        this.audio.currentTime = '00:00';
      }
      this.$emit('playAudio', this.isPlay);
    },
    // 当加载语音流元数据完成后,会触发该事件的回调函数
    // 语音元数据主要是语音的长度之类的数据
    // 结束时间
    onLoadedmetadata(res) {
      const maxTime = !this.data.filePath ? 0 : res.target.duration;
      this.audio.maxTime = parseInt(maxTime);
    },
    // 当timeupdate事件大概每秒一次,用来更新音频流的当前播放时间
    // 当音频当前时间改变后,进度条也要改变
    onTimeupdate(res) {
      this.audio.currentTime = res.target.currentTime;
      this.sliderTime = parseInt(
        (Math.floor(this.audio.currentTime) / this.audio.maxTime) * 100
      );
    },
    // 进度条拖动
    progressHandleTouch(type, e) {
      if (!(this.data && this.data.filePath)) {
        return;
      }
      if (type === 'start') {
        this.setValue(e.touches[0]);
      } else {
        this.setValue(e.changedTouches[0]);
      }
      if (type === 'end') {
        this.isPlay = true;
        this.$refs.audio.play();
      }
      this.$emit('playAudio', this.isPlay);
    },
    // 从点击位置更新 value
    setValue(e) {
      const $el = this.$el;
      const { maxTime, minTime, step } = this.audio;
      let value =
        ((e.clientX - $el.getBoundingClientRect().left) / $el.offsetWidth) *
        (maxTime - minTime);
      value = Math.round(value / step) * step + minTime;
      value = parseFloat(value.toFixed(5));

      if (value > maxTime) {
        value = maxTime;
      } else if (value < minTime) {
        value = minTime;
      }
      this.$refs.audio.currentTime = value;
    },
  },
};
</script>

你可能感兴趣的:(JS,vue,javascript,vue)