使用vue制作一个属于自己的音乐播放器

前言

其中在想在博客中添加音乐播放功能的时候,也考虑也其它音乐播放器插件如APlayer,页面和功能都能满足要求。而且播放页面也很好看,功能几乎都有。但是我不需要那么多功能,所以我自己尝试制作一个属于自己博客的音乐播放器。页面布局及样式参考APlayer

案例预览

<style>
        .isshow {
          left: -66px !important;
        }
        .music-row {
          height: 66px;
          bottom: 0px;
          left: 0;
          z-index: 999;
          transition: all 0.5s;
          margin-top: 60px;
        }
        .music-row:hover {
          left: 0px !important;
        }
        .music-row .music {
          transition: all 0.3s;
          display: flex;
          justify-content: left;
        }
        .music-row .music .music-img {
          position: relative;
          height: 66px;
          width: 66px;
          cursor: pointer;
        }
        .music-row .music .music-img:hover .music-toggle {
          color: var(--main-5);
          font-size: 25px;
        }
        .music-row .music .music-img .music-toggle {
          width: 30px;
          height: 30px;
          font-size: 20px;
          color: var(--main-6);
          text-align: center;
          line-height: 30px;
          position: absolute;
          bottom: 50%;
          right: 50%;
          transform: translate(50%,50%);
          transition: all 0.3s;
        }
        .music-row .music .music-img .music-toggle:hover {
          color: var(--main-5);
        }
        .music-row .music .music-img .musicActive {
          bottom: 0px;
          right: 0px;
          transform: translate(0%,0%);
        }
        .music-row .music .music-content {
          width: 334px;
          height: 66px;
          border-top: 1px solid #e9e9e9;
          padding: 3px 5px;
          background-color: #fff;
          box-sizing: border-box;
          position: relative;
          display: flex;
          flex-wrap: wrap;
        }
        .music-row .music .music-content .music-list {
          width: 100%;
          height: 100px;
          background-color: #fff;
          position: absolute;
          top: -100px;
          left: 0;
          margin: 0;
          padding: 5px;
          overflow: auto;
          box-sizing: border-box;
          border-bottom: 1px solid #ccc;
          border-top-left-radius: 4px;
          border-top-right-radius: 4px;
        }
        .music-row .music .music-content .music-list li {
          height: 30px;
          line-height: 30px;
          font-size: 14px;
          padding: 0 4px;
          margin: 2px 0;
          color: var(--main-6);
          background-color: #f8f9f9;
          transition: all 0.3s;
          cursor: pointer;
          display: flex;
          justify-content: space-between;
        }
        .music-row .music .music-content .music-list li span {
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
        }
        .music-row .music .music-content .active {
          color: #f56c6c !important;
          border-left: 3px solid #f56c6c;
        }
        .music-row .music .music-content .cont-top {
          overflow: hidden;
          white-space: nowrap;
          text-overflow: ellipsis;
          font-size: 15px;
          width: 65%;
          height: 40px;
          line-height: 40px;
        }
        .music-row .music .music-content .cont-cont {
          position: absolute;
          top: 3px;
          right: 0;
        }
        .music-row .music .music-content .cont-cont .cont-itme {
          display: inline-block;
          width: 30px;
          height: 40px;
          text-align: center;
          line-height: 40px;
          font-size: 18px;
          transition: all 0.2s;
        }
        .music-row .music .music-content .cont-cont .cont-itme:hover {
          cursor: pointer;
          color: #ccc;
        }
        .music-row .music .music-content .cont-bottom {
          position: absolute;
          bottom: 0;
          left: 0;
          width: 100%;
          height: 28px;
          display: flex;
          justify-content: left;
          padding: 0 5px;
          box-sizing: border-box;
        }
        .music-row .music .music-content .cont-bottom .bottom-progress {
          width: 80%;
          display: flex;
          align-items: center;
        }
        .music-row .music .music-content .cont-bottom .time {
          font-size: 12px;
        }
        .music-row .music .music-content .cont-bottom .music-func {
          line-height: 28px;
        }
        .music-row .music .music-content .cont-bottom .music-func span {
          margin: 0 3px;
          cursor: pointer;
        }
        .music-row .music .music-btn {
          height: 66px;
          width: 18px;
          background-color: #ccc;
          cursor: pointer;
          line-height: 66px;
          border-bottom-right-radius: 4px;
          border-top-right-radius: 4px;
        }
        
        </style>
        <link href="https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.2/theme-chalk/index.css" rel="stylesheet">
        <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.min.js"></script>
        <script src="https://cdn.bootcdn.net/ajax/libs/element-ui/2.13.2/index.js"></script>
        <div id="app">
                    <el-row class="music-row" :class="{isshow:isShow}">
                        <el-col :md="24" class="music">
                            <!-- <audio id="music" :src="musicInfo.url"></audio> -->
                            <!-- 音乐图片 -->
        
                            <div class="music-img">
                                <el-avatar class="music-img" :size="66" shape="square" :src="musicInfo.pic">
                                    <i class="el-icon-loading"></i>
                                    <!-- <img src="https://cube.elemecdn.com/e/fd/0fc7d20532fdaf769a25683617711png.png"/> -->
                                </el-avatar>
                                <span :class="{musicActive:isPlay}" @click="pause" class="iconfont music-toggle"><span :class="isPlay?'el-icon-video-pause':'el-icon-video-play'"></span>
                            </span></div>
                            <!-- 展开模块 -->
                            <transition name="el-zoom-in-center">
                                <div v-show="muIsShow" class="music-content">
                                    <transition name="el-zoom-in-bottom">
                                        <!-- 音乐列表模块 -->
                                        <div v-show="isList" class="music-list scrollbar">
                                            <el-scrollbar style="width: 100%;
                    height: 100%;">
                                                <ul style="padding:0">
                                                    <li :class="{active:index==ind}" @click="index=ind" v-for="(item,ind) of musics" :key="item.musicId">
                                                        <span>
                                                            {{ind+1}}
                                                            <span>{{item.title}}</span>
                                                        </span>
                                                        <span>{{item.name}}</span>
                                                    </li>
                                                </ul>
                                            </el-scrollbar>
                                        </div>
                                    </transition>
                                    <!-- 标题 作者 -->
                                    <div class="cont-top">
                                        <span>{{musics[index].title}}</span>
                                        <span>---</span>
                                        <span>{{musics[index].name}}</span>
                                    </div>
                                    <!--暂停 快进   -->
                                    <div class="cont-cont">
                                        <span class="cont-itme el-icon-d-arrow-left" @click="index=index==0?musics.length-1:index-1"></span>
                                        <span @click="pause" class="cont-itme iconfont" :class="isPlay?'el-icon-video-pause':'el-icon-video-play'"></span>
                                        <span class="cont-itme el-icon-d-arrow-right" @click="index=index==musics.length-1?0:index+1"></span>
                                        <span class="cont-itme el-icon-menu" @click="isList=!isList"></span>
                                    </div>
                                    <!-- 音乐拖动条 时间 -->
                                    <div class="cont-bottom">
                                        <div class="bottom-progress">
                                            <el-slider style="width:80%" tooltip-class="content-bg8" :format-tooltip="transTime" @change="getVal()" input-size="mini" :min="0" :max="max" v-model="numb"></el-slider>
                                            <!-- <input  class="bottom-range" v-model="numb" type="range" min="0" :max="max" @input="getVal()"  :style="{background: '-webkit-linear-gradient(top, var(--main-5), var(--main-5)) 0% 0% / '+ numb*100/max +'% 100% no-repeat'}"/> -->
                                            <span class="time" style="padding-left:10px">{{newTime}}</span>
                                            <span class="time">/</span>
                                            <span class="time">{{time}}</span>
                                        </div>
                                        <!-- 循环播放  -->
                                        <div class="music-func">
                                            <span @click="cycle=cycle==2?0:cycle+1" class="cont-itme iconfont" :class="cycle==0?'el-icon-finished':cycle==1?'el-icon-refresh':'el-icon-sort'"></span>
                                        </div>
                                    </div>
                                </div>
                            </transition>
                            <!-- 扩展栏 -->
                            <div class="music-btn" @click="MuBtnClick">
                                <i :class="muIsShow?'el-icon-arrow-left':'el-icon-arrow-right'"></i>
                            </div>
                        </el-col>
                    </el-row>
                </div>
                <script>
                    var Main = {
                        data() {
                            return {
                                index: 0, //播放列表
                                muIsShow: false, //是否显示
                                isPlay: false, //是否播放
                                canplay: false, //是否能播放
                                loading: false, //是否自动播放
                                cycle: 0,
                                numb: 0,
                                time: "00:00",
                                newTime: "00:00",
                                max: 0,
                                audio: "",
                                musicInfo: {},
                                isList: false,
                                isShow: false,
                                setTimeout: null,
                                musics: [
                                    {
                                        "music_id": "1463165983",
                                        "title": "最美的期待",
                                        "name": "周笔畅",
                                        "type": "netease",
                                        "url":'https://www.0dutv.com/plug/down/up2.php/212877015.mp3',
                                        "pic":'https://p.pstatp.com/origin/1372100011fb653db9634'
                                    }, {
                                        "music_id": "515453363",
                                        "title": "过客",
                                        "name": "阿涵",
                                        "type": "netease",
                                        "url":'https://www.0dutv.com/plug/down/up2.php/109717925.mp3',
                                        "pic":'https://p.pstatp.com/origin/1372100011fb653db9634'
                                    },
                                ]
                            }
                        },
                        methods: {
                            // 打开和关闭音乐收缩栏
                            MuBtnClick() {
                                this.muIsShow = !this.muIsShow;
                                this.hidden(1500);
                            },
                            hidden(time) {
                                if (this.muIsShow == false) {
                                    this.setTimeout = setTimeout(() => {
                                        this.isShow = true;
                                    }, time);
                                } else {
                                    clearTimeout(this.setTimeout);
                                    this.isShow = false;
                                }
                            },
                            // 播放暂停
                            pause() {
                                if (this.audio !== null && this.canplay) {
                                    this.loading = true;
                                    if (this.audio.paused) {
                                        this.audio.play(); // 播放
                                        this.isPlay = true;
                                    } else {
                                        this.audio.pause(); // 暂停
                                        this.isPlay = false;
                                        console.log("暂停被调用了");
                                    }
                                } else {
                                    this.$message({
                                        showClose: true,
                                        message: "音乐还没有加载成功呢!",
                                        type: "warning",
                                    });
                                }
                            },
                            // 快进音乐
                            getVal() {
                                if (!this.audio.paused || this.audio.currentTime != 0) {
                                    this.audio.currentTime = this.numb;
                                    if (this.numb == Math.floor(this.max)) {
                                        this.audio.pause();
                                        this.isPlay = false;
                                    }
                                }
                            },
                            // 获取音乐总时长
                            getTime() {
                                let time = this.audio.duration;
                                this.max = time;
                                //总共时长的秒数
                                this.time = this.transTime(time);
                            },
                            // 时间格式化位00:00
                            formatTime(value) {
                                let time = "";
                                let s = value.split(":");
                                let i = 0;
                                for (; i < s.length - 1; i++) {
                                    time += s[i].length == 1 ? "0" + s[i] : s[i];
                                    time += ":";
                                }
                                time += s[i].length == 1 ? "0" + s[i] : s[i];
                                return time;
                            },
                            // 把毫秒变成时分秒
                            transTime(value) {
                                let time = "";
                                let h = parseInt(value / 3600);
                                value %= 3600;
                                let m = parseInt(value / 60);
                                let s = parseInt(value % 60);
                                if (h > 0) {
                                    time = this.formatTime(h + ":" + m + ":" + s);
                                } else {
                                    time = this.formatTime(m + ":" + s);
                                }
                                return time;
                            },
                            getMusic() {
                                if (!this.musics[this.index].pause) {
                                    this.musicInfo = this.musics[this.index]
                                    this.audio.src = this.musics[this.index].url;
                                    // console.log("获取音乐");
                                    // const qs = require("qs");
                                    // let that = this;
                                    // console.log(that.musics[that.index].type);
                                    // this.$post(
                                    //         "/music",
                                    //         qs.stringify({
                                    //             input: that.musics[that.index].music_id,
                                    //             filter: "id",
                                    //             type: that.musics[that.index].type,
                                    //             page: 1,
                                    //         })
                                    //     )
                                    //     .then(function(res) {
                                    //         that.musicInfo = res.data[0];
                                    //         that.audio.src = that.musicInfo.url;
                                    //     })
                                    //     .catch(function(error) {
                                    //         that.audio.pause(); // 暂停
                                    //         that.isPlay = false;
                                    //     });
                                } else {
                                    console.log(this.index);
                                    this.musicInfo = {
                                        title: this.musics[this.index].title,
                                        author: this.musics[this.index].name,
                                        pic: this.musics[this.index].img,
                                        url: this.musics[this.index].url,
                                    };
                                    this.audio.src = this.musics[this.index].url;
                                }
                            },
                            // 获取我的音乐列表
                            getList() {
                                this.index = Math.floor(Math.random() * this.musics.length);
                                this.length = this.musics.length;
                                this.getMusic();
                                // let that = this;
                                // this.$get("url")
                                //   .then(function (res) {
                                //     that.musics = res.data;
                                //     that.index = Math.floor(Math.random() * that.musics.length);
                                //     that.length = that.musics.length;
                                //     that.getMusic();
                                //   })
                                //   .catch(function (error) {});
                            },
                            mError() {
                                  if (this.loading) {
                                    console.log("出错");
                                    this.$message({
                                      showClose: true,
                                      message: "播放错误,自动播放下一首",
                                      type: "error",
                                    });
                                    if (this.musics[this.index].musicInfo) {
                                      delete this.musics[this.index].musicInfo;
                                    }
                                    this.index = this.index == this.musics.length - 1 ? 0 : this.index + 1;
                                  }
                                },
                                mCanplay() {
                                  this.canplay = true;
                                  if (this.loading) {
                                    this.audio.play(); // 播放
                                    this.isPlay = true;
                                  }
                                  this.getTime();
                                },
                                mTimeUpdate() {
                                  this.numb = this.audio.currentTime;
                                  this.newTime = this.transTime(this.audio.currentTime);
                                },
                                mEnded() {
                                  if (this.cycle == 0) {
                                    this.audio.pause(); // 暂停
                                    this.isPlay = false;
                                  } else if (this.cycle == 1) {
                                    this.audio.play(); // 播放
                                    this.isPlay = true;
                                  } else {
                                    this.index = this.index == this.musics.length - 1 ? 0 : this.index + 1;
                                  }
                                },
                        },
                        mounted() {
                            this.hidden(5000);
                            let that = this;
                        },
                         created() {
                           // this.audio=document.getElementById('music')
                           this.audio = document.createElement("audio");
                           this.getList();
                           let that = this;
                           this.audio.addEventListener("canplay", that.mCanplay, false),
                           this.audio.addEventListener("timeupdate", that.mTimeUpdate, false);
                           this.audio.addEventListener("ended", that.mEnded, false);
                           this.audio.addEventListener("error", that.mError, false);
                         },
                          beforeDestroy() {
                             let that=this
                             this.audio.removeEventListener("canplay", that.mCanplay);
                             this.audio.removeEventListener("ended", that.mEnded);
                             this.audio.removeEventListener("error", that.mError);
                             this.audio.removeEventListener("timeupdate", that.mTimeUpdate);
                           },
                        watch: {
                            index(val) {
                                if (this.loading) {
                                    this.audio.play(); // 播放
                                    this.isPlay = true;
                                }
                                this.canplay = false;
                                this.audio.currentTime = 0;
                                // this.audio.pause();
                                this.audio.src = "";
                                this.getMusic();
                            },
                        },
                    }
                    var Ctor = Vue.extend(Main)
                    new Ctor().$mount(document.getElementById('app'))
                </script>

了解audio

html标签

<audio src="http://www.0dutv.com/plug/down/up2.php/109717925.mp3" controls="controls">
Your browser does not support the audio element.
</audio>

属性

属性 描述
autoplay autoplay 如果出现该属性,则音频在就绪后马上播放。
controls controls 如果出现该属性,则向用户显示控件,比如播放按钮。
loop loop 如果出现该属性,则每当音频结束时重新开始播放。
muted muted 规定视频输出应该被静音。
preload preload 如果出现该属性,则音频在页面加载时进行加载,并预备播放。如果使用 "autoplay",则忽略该属性。
src url 要播放的音频的 URL。

内容来源---W3School

js创建(本案例使用)

//创建audio,不会在页面中显示。
 var audio=document.createElement("audio");
//设置src,播放地址。
audio.src ='http://url'

事件

属性 描述
oncanplay script 当文件就绪可以开始播放时运行的脚本(缓冲已足够开始时)。
oncanplaythrough script 当媒介能够无需因缓冲而停止即可播放至结尾时运行的脚本。
onended script 当媒介已到达结尾时运行的脚本(可发送类似“感谢观看”之类的消息
onpause script 当媒介被用户或程序暂停时运行的脚本。
onplay script 当媒介已就绪可以开始播放时运行的脚本。
onplaying script 当媒介已开始播放时运行的脚本。
onprogress script 当浏览器正在获取媒介数据时运行的脚本。
ontimeupdate script 当播放位置改变时(比如当用户快进到媒介中一个不同的位置时)运行的脚本。

内容来源---W3School

案例准备

格式化时间

// 获取音乐总时长
    getTime() {
      let time = this.audio.duration;
      this.max = time;
      //总共时长的秒数
      this.time = this.transTime(time);
    },
    // 时间格式化位00:00
    formatTime(value) {
      let time = "";
      let s = value.split(":");
      let i = 0;
      for (; i < s.length - 1; i++) {
        time += s[i].length == 1 ? "0" + s[i] : s[i];
        time += ":";
      }
      time += s[i].length == 1 ? "0" + s[i] : s[i];
      return time;
    },
    // 把毫秒变成时分秒
    transTime(value) {
      let time = "";
      let h = parseInt(value / 3600);
      value %= 3600;
      let m = parseInt(value / 60);
      let s = parseInt(value % 60);
      if (h > 0) {
        time = this.formatTime(h + ":" + m + ":" + s);
      } else {
        time = this.formatTime(m + ":" + s);
      }
      return time;
    },

创建及绑定事件

created() {
    // 创建Audio  
    this.audio = document.createElement("audio");
    this.getList();
    let that = this;
    // 当音乐准备就绪时的操作
    this.audio.addEventListener(
      "canplay",
      function () {
        console.log("加载成功");
        console.log(that.musicInfo.url);
        that.canplay = true;
    //防止自动播放
        if (that.loading) {
          that.audio.play(); // 播放
          that.isPlay = true;
        }
        that.getTime();
        // that.pause()
      },
      false
    ),
//快进时的操作,同步时间
      this.audio.addEventListener(
        "timeupdate",
        function () {
          that.numb = that.audio.currentTime;
          that.newTime = that.transTime(that.audio.currentTime);
        },
        false
      );
//当音乐播放到结束后的操作,
    this.audio.addEventListener(
      "ended",
      function () {
        if (that.cycle == 0) {
          that.audio.pause(); // 暂停
          that.isPlay = false;
        } else if (that.cycle == 1) {
          that.audio.play(); // 播放
          that.isPlay = true;
        } else {
            that.index == that.musics.length - 1 ? 0 : that.index + 1;
        }
      },
      false
    );
  },

播放暂停、快进

// 播放暂停
    pause() {
      if (this.audio !== null && this.canplay) {
        this.loading = true;
        if (this.audio.paused) {
          this.audio.play(); // 播放
          this.isPlay = true;
        } else {
          this.audio.pause(); // 暂停
          this.isPlay = false;
          console.log("暂停被调用了");
        }
      } else {
        this.$message({
          showClose: true,
          message: "音乐还没有加载成功呢!",
          type: "warning",
        });
      }
    },
    // 快进音乐
    getVal() {
      if (!this.audio.paused || this.audio.currentTime != 0) {
        this.audio.currentTime = this.numb;
        if (this.numb == Math.floor(this.max)) {
          this.audio.pause();
          this.isPlay = false;
        }
      }
    },

切换

主要时通过监听器,监听音乐id的变化来切换歌曲

 watch: {
    index(val) {
      if (this.loading) {
        this.audio.play(); // 播放
        this.isPlay = true;
      }
      this.canplay = false;
      this.audio.currentTime = 0;
      // this.audio.pause();
      this.audio.src = "";
      this.getMusic();
    },
  },
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。