vue2 使用el-slider滑块作为音乐播放器进度条 可拖动改变音频进度

以下是包含一个element ui里的el-slider滑块作为音频播放器组件的进度条,其中包括播放/暂停按钮、上一首/下一首按钮、作者信息、音频时长、播放进度条等功能,直接上代码:

<template>
  <div class="container">
    <div class="middlebox">
      <div class="top">
        <!-- 播放 -->
        <div class="play-box">
          <div class="playbtn-box">
            <!-- 上一首 -->
            <img
              class="leftbtn"
              @click="nextSong()"
              src="@/assets/zuo@2x.png"
              alt=""
            />
            <!-- 播放 -->
            <audio
              ref="audio"
              id="audio"
              autoplay
              controls="controls"
              style="display: none"
              :src="audioSrc"
              @pause="onPause"
              @play="onPlay"
              @timeupdate="handleAudioTimeUpdated"
              @loadedmetadata="onLoadedmetadata"
            ></audio>
            <div class="cenbtn" @click="playaudio()">
              <img src="@/assets/yuan@2x.png" alt="" />
              <div class="btn">
                <img
                  v-if="audio.playing"
                  class="plays"
                  @click="onPlay()"
                  src="@/assets/bofang@2x.png"
                  alt=""
                />
                <img
                  v-else
                  class="pauses"
                  @click="onPause()"
                  src="@/assets/zanting@2x.png"
                  alt=""
                />
              </div>
            </div>
            <!-- 下一首 -->
            <img
              @click="prevSong()"
              class="nextbtn"
              src="@/assets/you@2x.png"
              alt=""
            />
          </div>
        </div>
        <div class="progress-box">
          <div class="albumbox">
            <h3>第一集</h3>
            <div class="author-box">
              <h2>作者:天伊</h2>
              <h1>
                {{ audio.currentTime | formatSecond }}/{{
                  datas.duration | formatSecond
                }}
              </h1>
            </div>
            <!-- 进度条 -->
            <div class="progress-bar">
              <div class="tab-player-progress">
                <el-slider
                  @change="progressChange"
                  v-model="audio.currentTime"
                  :format-tooltip="realFormatSecond"
                  :max="Number(datas.duration)"
                  @mouseup.native="mouseupChangeTime"
                ></el-slider>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>
<script>
// 将整数转换成 时:分:秒的格式
function realFormatSecond(second) {
  var secondType = typeof second;

  if (secondType === "number" || secondType === "string") {
    second = parseInt(second);
    var mimute = Math.floor(second / 60);
    second = second - mimute * 60;

    return ("0" + mimute).slice(-2) + ":" + ("0" + second).slice(-2);
  } else {
    return "00:00";
  }
}
export default {
  filters: {
    // 将整数转化成时分秒
    formatSecond(second = 0) {
      return realFormatSecond(second);
    },
  },
  data() {
    return {
      audioUrl: Common.audioUrl(),
      datas: {
        fileUrl: "", //音频地址
        albumId: "", //专辑id
        duration: 0, //时长
      },
      audio: {
        playing: false, // 该字段是音频是否处于播放状态的属性
        currentTime: 0, // 音频当前播放时长
      },
      audioKey: 0,
      recordsList: [], //专辑列表
      cacheCurrent: 0,
    };
  },
  computed: {
    audioSrc() {
      let url = this.audioUrl + this.datas.fileUrl;
      return url;
    },
  },
  methods: {
    // 播放音频
    play() {
      this.$refs.audio.play();
    },
    // 暂停音频
    pause() {
      this.$refs.audio.pause();
    },
    // 音频播放
    onPlay() {
      this.audio.playing = true;
    },
    // 当音频暂停
    onPause() {
      this.audio.playing = false;
    },
    // 控制音频的播放与暂停
    playaudio() {
      return this.audio.playing ? this.pause() : this.play();
    },
    //获取音频长度
    onLoadedmetadata(res) {
      this.datas.duration = parseInt(res.target.duration);
    },
    //进度条触发事件
    realFormatSecond(second) {
      this.cacheCurrent = second;
      return realFormatSecond(second);
    },
    // 当音频当前时间改变后,进度条也要改变
    handleAudioTimeUpdated(res) {
      this.audio.currentTime = res.target.currentTime;
      // );
    },
    // 鼠标抬起改变当前时间点
    mouseupChangeTime() {
      this.progressChange(this.cacheCurrent);
    },
    // 拖动进度滚动条
    progressChange(value) {
      this.$refs.audio.currentTime = value >= 0 ? value : this.cacheCurrent;
      this.audio.currentTime = value >= 0 ? value : this.cacheCurrent;
    },
    // 播放上一首歌曲
    nextSong() {
      this.setPageCounts();
      this.pause();
      this.audioKey -= 1;

      if (this.audioKey < 0) {
        this.audioKey = this.recordsList.length - 1;
      }
      const newArr = this.recordsList.find(
        (item, index) => index == this.audioKey
      );
      this.datas.title = newArr.title;
      this.datas.fileUrl = newArr.fileUrl;
      this.$nextTick(() => {
        this.play();
      });
    },
    // 播放下一首歌曲
    prevSong() {
      this.pause();

      this.audioKey += 1;
      if (this.audioKey >= this.recordsList.length) {
        this.audioKey = 0;
      }
      const newArr = this.recordsList.find(
        (item, index) => index == this.audioKey
      );
      this.datas.fileUrl = newArr.fileUrl;
      this.$nextTick(() => {
        this.play();
      });
    },
  },
};
</script>
<style scoped lang="less">
.middlebox {
  width: 880px;
  height: 140px;
  margin-left: 60px;
  .top {
    position: relative;
    width: 100%;
    height: 100%;
    margin-top: 70px;
    .play-box {
      position: absolute;
      right: -50px;
      display: flex;
      justify-content: space-between;
      width: 306px;
    }
    .playbtn-box {
      display: flex;
      justify-content: center;
      align-items: center;
      width: 120px;
      .cenbtn {
        position: relative;
        margin: 0 15px;
        .plays {
          position: absolute;
          top: 50%;
          left: 50%;
          transform: translate(-50%, -50%);
          width: 16px;
          height: 27px;
        }
        .pauses {
          position: absolute;
          top: 50%;
          left: 55%;
          transform: translate(-50%, -50%);
          width: 22px;
          height: 26px;
        }
      }
    }
    .volume-box {
      width: 145px;
      display: flex;
      justify-content: center;
      align-items: center;
      .volumImg {
        width: 18px;
        height: 17px;
      }
    }
    .progress-box {
      position: absolute;
      left: 0;
      bottom: -20px;
      display: flex;
      justify-content: space-between;
      width: 100%;
      height: 100px;
      .albumImg {
        width: 90px;
        border-radius: 50%;
        margin-right: 15px;
      }
      .albumbox {
        cursor: pointer;
        width: 100%;
        h3 {
          font-size: 18px;
          font-weight: 400;
          color: #1c1c1c;
          margin: 0;
          width: 90%;
        }
        .author-box {
          display: flex;
          justify-content: space-between;
          height: 60px;
          h2 {
            font-size: 14px;
            font-weight: 400;
            color: #a4a4a4;
            line-height: 40px;
          }
          h1 {
            font-size: 14px;
            font-weight: 400;
            color: #4a4a4a;
          }
        }
        .progress-bar {
          position: relative;
          width: 100%;
          margin: 0px auto;
          text-align: left;
        }
        .timer {
          vertical-align: sub;
          font-size: 20px;
          font-family: PingFang SC;
          font-weight: 500;
          color: #b1b1b1;
          position: absolute;
          left: 20px;
          top: 0;
          transform: translateY(-50%);
        }
        .timers {
          vertical-align: sub;
          font-size: 20px;
          font-family: PingFang SC;
          font-weight: 500;
          color: #b1b1b1;
          position: absolute;
          right: 20px;
          top: 0;
          transform: translateY(-50%);
        }
        // 进度条
        .p_slider {
          width: 100%;
          position: relative;
          height: 24px;
          display: flex;
          align-items: center;
          cursor: default;
          user-select: none;
          outline: none;
        }

        .p_slider_track {
          position: absolute;
          height: 5px;
          left: 0;
          right: 0;
          top: 50%;
          margin-top: -1px;
          background-color: #e6e6e6;
        }

        .p_slider_fill {
          position: absolute;
          height: 4px;
          width: 100%;
          background-color: #ff821e;
          left: 0;
          top: 50%;
          margin-top: -1px;
        }
        .p-box {
          position: relative;
          width: 100px;
          height: 100px;
          margin-top: -100px;
        }
        .p_slider_thumb {
          position: absolute;
          top: 100%;
          width: 15px;
          height: 15px;
          background-color: #ff821e;
          color: #ff821e;
          border-radius: 50%;
          transform: translate(-50%, -50%);
          cursor: pointer;
        }
      }
    }
  }
}
</style>

  • 19
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值