vue中可以用的音频播放demo,可以作为组件引入

vue中可以用的音频播放demo,可以作为组件引入

 

参考文章:

https://segmentfault.com/a/1190000012453975

https://blog.csdn.net/xzwwjl1314/article/details/107204842/

 

其中主要参考第二篇,但在进度条拖动上,获取鼠标当前位置遇到问题。

clickProgress这个方法

const position = e.clientX - e.currentTarget.offsetLeft

这个地方获取的e.clientX值为900多,是变化的,但是e.currentTarget.offsetLeft的值一直是41,导致一拖动按照百分比计算的播放时间直接因为分子太大直接到底

后面发下在0的位置,是917, e.clientX为变化,923,957,依次变化,变化的值就是点击后的当前鼠标位置

所以用 (e.clientX-917)/ 进度条总宽度 * 总时长,获得跳转时长

 

4/20 update:

clickProgress方法这里的固定距离,写死的917遇到不同情况会失效,因为917不可以写死。
后续根据屏幕估算,用了document.body.clientWidth * 0.74代替写死的数值
const fixedSpace = document.body.clientWidth * 0.74; // 这是根据屏幕估算的
 
    clickProgress(event) {
      console.log(event);
      // 点击进度条时 更新音频时间和进度条
      const e = event || window.event;
      const position = e.clientX - e.currentTarget.offsetLeft; // 当前点击的位置
      const progressWidth = this.$refs.progress.offsetWidth; // 进度条总宽度
      // 第一步确认固定距离 878  减去固定距离就是剩余距离
      const fixedSpace = document.body.clientWidth * 0.74; // 这是根据屏幕估算的
      const space = position - fixedSpace;
      this.$refs.audio.currentTime = (space / progressWidth) * this.duration;
      this.updateProgress(
        (position / progressWidth) * this.duration,
        this.duration
      );
    },

 

 

<template>
  <div>
    <div class="ckplayer">
      <div class="bottom-progress">
        <div class="curTime">{{ curTime ? curTime : "00:00" }}</div>
        <div class="progress" @click="clickProgress($event)" ref="progress">
          <div class="line" :style="{ width: `${precent}` }"></div>
          <div
            class="dot"
            :style="{ left: `${precent}` }"
            @touchstart="dotStart"
            @touchmove="dotMove"
            @touchend="dotEnd"
          ></div>
        </div>
        <div class="allTime">{{ allTime }}</div>
      </div>
      <div class="bottom-controls">
        <div class="prev" @click="prevSong">
          <!-- <i class="pre"></i> -->
        </div>
        <div class="pause" v-show="isPlaying" @click="pauseSong">
          <!-- <i class="fa fa-pause">暂停</i> -->
        </div>
        <div class="play" v-show="!isPlaying" @click="playSong">
          <!-- <i class="fa fa-play">播放</i> -->
        </div>
        <div class="next" @click="nextSong"></div>
      </div>
      <!-- autio标签 -->
      <audio
        @timeupdate="updateTime"
        @canplay="getDuration"
        @ended="ended"
        :src="musicUrl"
        id="audio"
        ref="audio"
        class="testAudio"
      ></audio>
    </div>
  </div>
</template>

<script>
import { boardListDetail } from "@/utils/api";
export default {
  data() {
    return {
      list: [],
      tvUrl: "",
      player: null,
      playingSong: {}, // 正在播放的歌曲信息
      show: true, // 控制cd和lyrics的显示 默认显示cd
      isPlaying: false, // 播放和暂停状态
      musicUrl: "", // 音乐地址
      curTime: "00:00", // 当前播放时间,格式化之后的
      allTime: "00:00", // 当前音频总时长,格式化之后的
      duration: 0, // 音频总时长,单位秒
      currentTime: 0, // 音频当前播放时间, 单位秒
      precent: "0%", // 当前播放进度百分比
      touchInfo: {}, // 原点滑动时的位置信息
      lyrics: {}, // 歌词 中英文
      lyricsObjArr: [], // 处理之后的歌词 包含时间和歌词
      curMsTime: "", // 当前音频播放的时分毫秒
      like: false, // 是否喜欢当前歌曲 默认为不喜欢
      lyricIndex: "0", // 当前显示的歌词
      isMuted: false, // 是否经验 默认不静音
      volume: 100, // 音频音量
      likeList: [],
      playType: 0, // 播放类型 0代表播放单曲 1代表播放歌曲列表
      audios: [],
      index: 0,
    };
  },
  components: {},
  created() {
    this.getAudio();
    this.loadMusic(this.index);
    this.playType = this.audios.length === 1 ? 0 : 1;
  },
  mounted() {},
  methods: {
    async getAudio() {
      const res = await boardListDetail({
        page: this.page,
        pagesize: this.pagesize,
      });
      this.audios = res.data.items[0].audio_path;
      this.loadMusic(this.index);
    },
    clickProgress(event) {
      console.log(event);
      // 点击进度条时 更新音频时间和进度条
      const e = event || window.event;
      const position = e.clientX - e.currentTarget.offsetLeft; // 当前点击的位置
      const progressWidth = this.$refs.progress.offsetWidth; // 进度条总宽度
      // 第一步确认固定距离 878  减去固定距离就是剩余距离
      const fixedSpace = document.body.clientWidth * 0.74; // 这是根据屏幕估算的
      const space = position - fixedSpace;
      this.$refs.audio.currentTime = (space / progressWidth) * this.duration;
      this.updateProgress(
        (position / progressWidth) * this.duration,
        this.duration
      );
    },
    updateProgress(currentTime, duration) {
      // 更新进度条
      const precent = `${((currentTime / duration) * 100).toFixed(5)}%`;
      this.precent = precent;
    },
    dotEnd(e) {
      this.playSong();
      this.isPlaying = true;
    },
    dotMove(e) {
      console.log(e);
      // 移动的距离
      let moveX = e.touches[0].pageX - 83;
      // console.log(moveX, "kk");
      // 进度条的宽度
      const progressWidth = this.$refs.progress.offsetWidth;
      if (moveX >= progressWidth) moveX = progressWidth;
      this.$refs.audio.currentTime = (moveX / progressWidth) * this.duration;
      this.updateProgress(
        (moveX / progressWidth) * this.duration,
        this.duration
      );
    },
    dotStart(e) {
      // 点击的初始位置
      this.touchInfo.startX = e.touches[0].pageX - 83;
    },
    formatTime(time) {
      if (time === 0) {
        this.curTime = "00:00";
        return;
      }
      const mins =
        Math.floor(time / 60) < 10
          ? `0${Math.floor(time / 60)}`
          : Math.floor(time / 60);
      const sec =
        Math.floor(time % 60) < 10
          ? `0${Math.floor(time % 60)}`
          : Math.floor(time % 60);
      return `${mins}:${sec}`;
    },
    ended() {
      this.$refs.audio.currentTime = 0;
      this.isPlaying = false;
      // if (this.playType === 0) {
      //   this.$message.warning("歌曲列表只有这一首 请返回上一级!");
      //   this.curTime = "00:00";
      //   return;
      // }
      // if (this.index >= this.audios.length - 1) {
      // }
      this.nextSong();
      console.log("播放完毕");
      this.curTime = "00:00";
    },
    updateTime(e) {
      // timeupdate时获取当前播放时间
      const { currentTime } = e.target;
      // console.log(e.target.currentTime, "看看");
      this.currentTime = currentTime;
      this.curTime =
        this.formatTime(currentTime) === "undefined"
          ? "00:00"
          : this.formatTime(currentTime);
      this.updateProgress(currentTime, this.duration);
      // console.log(this.formatTime(currentTime), "k");
    },
    loadMusic(index) {
      // 加载播放地址
      this.musicUrl = this.audios[index];
      console.log(this.musicUrl, this.audios[index]);
    },
    playSong() {
      console.log("5");
      // 手动点击播放歌曲
      const audio = this.$refs.audio;
      this.isPlaying = !this.isPlaying;
      audio.play();
    },
    autoPlaySong() {
      // 自动播放歌曲
      const audio = this.$refs.audio;
      audio.autoplay = true;
      this.isPlaying = true;
    },
    nextSong() {
      console.log("进下一首");
      this.$refs.audio.currentTime = 0;
      // this.isPlaying = false;
      this.curTime = "00:00";
      // 播放下一首歌曲
      this.index++;
      if (this.index > this.audios.length - 1) {
        this.index = 0;
      }
      console.log(this.index);
      this.loadMusic(this.index);
      this.autoPlaySong();
    },
    prevSong() {
      console.log("上一首");
      this.$refs.audio.currentTime = 0;
      // this.isPlaying = false;
      this.curTime = "00:00";
      // 播放上一首歌曲
      this.index--;
      if (this.index < 0) {
        this.index = this.audios.length - 1;
      }
      console.log(this.index, this.curTime);
      this.loadMusic(this.index);
      this.autoPlaySong();
    },
    pauseSong() {
      console.log("6");
      // 暂停歌曲
      this.isPlaying = !this.isPlaying;
      this.$refs.audio.pause();
    },
    getDuration() {
      // canplay时获取音频总时长
      this.duration = this.$refs.audio.duration;
      this.allTime = this.formatTime(this.$refs.audio.duration);
    },
  },
};
</script>

<style scoped lang="scss">
.ckplayer {
  width: 100%;
  height: 25vh;
  position: absolute;
  top: 7%;
  left: 5.5%;
  width: 89%;
  height: 82%;
  .testAudio {
    width: 100%;
    height: 100%;
    background: red;
  }
}

.bottom {
  height: 20%;
  color: #fff;
  &-line1 {
    font-size: 0.8vw;
    display: flex;
    align-items: center;
    justify-content: space-around;
  }
  &-progress {
    padding: 0 5%;
    // margin: 5% 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    .progress {
      height: 0.2vh;
      background-color: #fff;
      width: 70%;
      position: relative;
      .line {
        position: absolute;
        left: 0;
        top: 0;
        height: 0.1vh;
        background-color: skyblue;
        transition: width 0.1s;
      }
      .dot {
        width: 0.5vw;
        height: 1vh;
        border-radius: 50%;
        position: absolute;
        top: -0.4vh;
        background-color: #ccc;
        transition: left 0.1s;
      }
    }
  }
  &-controls {
    padding: 0 5%;
    display: flex;
    align-items: center;
    justify-content: space-around;
    font-size: 30px;
    padding: 0 3vw;
    .prev {
      width: 1.3vw;
      height: 2.5vh;
      background: url("../assets/pre.png") no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
    }
    .next {
      width: 1.3vw;
      height: 2.5vh;
      background: url("../assets/next.png") no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
    }
    .pause {
      width: 4vw;
      height: 8vh;
      background: url("../assets/pause.png") no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
    }
    .play {
      width: 4vw;
      height: 8vh;
      background: url("../assets/play.png") no-repeat;
      background-size: 100% 100%;
      cursor: pointer;
    }
  }
}
</style>

 

posted @ 2021-04-07 17:30  jane_panyiyun  阅读(479)  评论(0编辑  收藏  举报