📖手撸Vue 实现音乐播放功能
前言
因为之前一直想弄一个音乐播放的站点,但不知道用什么框架去写比较好,恰好看见一个可以用的网易云音乐API打算用来测试下
所以样式我就没怎么太注意去写了,功能也是简单实用的几个,可以用来挂着听歌(虽然没有软件好用)
代码量比较多,嫌麻烦的可以直接复制源码,源码我也写了很多译释,直接复制下来放到自己页面应该可以运行
框架:Vue-cli,jQuery,bootstrap,
音乐播放站点 》》
源码
废话不多说,直接上源码
<template> <div id="music"> <div class="b_img"><img src="../../assets/image/musicimg.jpg"></div> <div id="back_img"><div style="height:37px;background-color:#fff;z-index: 1;position: relative;"></div><img v-bind:src="muimg"></div> <div id="music_bo"> <div class="title"> <p class="title_h1">歌名:{{gename}}</p> <p class="title_info">歌手:<b v-for="name in usname">{{name}} </b></p> </div> <div class="in_left"><button @click="musicshang()" class="no_button"><i class="glyphicon glyphicon-step-backward" title="上一首"></i></button></div> <div class="in_img"><img v-bind:src="muimg" class="max_img"> <button class="zan_an" @click="bo()"><i class="glyphicon glyphicon-play" title="暂停"></i></button></div> <div class="in_right"> <button @click="musicxia()" class="no_button"><i class="glyphicon glyphicon-step-forward" title="下一首"></i></button> <button class="no_button list_ge" @click='gelist()'><i class="glyphicon glyphicon-th-large" title="歌单列表"></i></button> </div> <audio controls v-bind:src="bofangmu" id="xqt"></audio> </div> <button @click="shou()" class="ce_bun"><i class="glyphicon glyphicon-chevron-left"></i></button> <div id="ge_dan"> <div class="list-group"> <a href="javascript:;" class="list-group-item active"> <h4 class="list-group-item-heading">歌单</h4> </a> <ul class="listgun_ul"> <a href="javascript:;" class="list-group-item" v-for="list in gedan" @click='listfun(list.id)'> <h4 class="list-group-item-heading">{{list.name}}</h4> </a> </ul> </div> </div> </div> </template> <script> const axios = require('axios'); export default{ name:"music", data(){ return { music:[1364400123,480426313,1309896289,1344897943,1360740361,1426649237,1404906595,480353,2059056,29482234,1400256289,1406642934,1386259535,1409329655,1335580481,527957820,468176711,574566207,1316460171,536099160,534542079,1313354324,27890306,1328146041,31445554,552594869,471565190,480580003,425828896,29004400,514761281,536502758,1330348068,25706282,32083133,1460474276,4879345,524543708,427606780,1410840088,760037,492145159,461544312,507585220,411314681,465920383,21253966,28248872,1491585,1321385655,863046037,515601126,30212890,422132115,533465371,440208476,410802679,1313107065,438981337,465675773,5162502,17753288,29769734,21038748,409931224,534542015,18161816,2918954,463352636,26565006,19081573,28830412,26429346,466122460,21253958,444269135,440101136,418602088,19542383,455653437,27946894,468882985,19711382,29009655,466794339,32574252,3570196,1345018,461347998,36990266,28681438], bofangmu:'',//歌曲url muimg:'',//歌曲封面图片 gename:'',//歌曲名 usname:[],//歌手 gedan:[],//歌单 arynum:0,//获取上方歌曲ID shou_s:true//点击展开与隐藏 }; }, mounted(){ var that=this; this.axiosmu(this.music[this.arynum]); let player = document.getElementById('xqt'); player.ontimeupdate = function () { if(player.currentTime == player.duration){//判断当前歌曲是否播放完 that.musicxia();//执行下一首 } } }, methods:{ axiosmu(numb){//获取歌曲信息 var that =this;//解决this:null问题 axios.all([this.getUserAccount(numb), this.getUserPermissions(numb)])//并发执行函数 .then(axios.spread(function (acct, perms) { that.bofangmu = acct.data.data[0].url;//获取歌的链接 that.muimg =perms.data.songs[0].al.picUrl;//获取图片链接 that.gename =perms.data.songs[0].al.name;//获取歌名 for(let i=0;i<perms.data.songs[0].ar.length;i++){//循环获取歌手 that.usname[i]=perms.data.songs[0].ar[i].name; } })); }, getUserAccount(e) {return axios.get('https://api.imjad.cn/cloudmusic/?id='+e);},//获取音乐链接 getUserPermissions(e) {return axios.get('https://api.imjad.cn/cloudmusic/?type=detail&id='+e);},//获取图像 musicxia(){//下一首 let ap = this.music[this.arynum+=1]; if(this.arynum>=this.music.length){ this.arynum=0; this.axiosmu(ap);//发送下一首ID }else{ let that=this; this.axiosmu(ap); setTimeout(function () {//利用定时器功能下一首时,自动播放 that.xia_bo(); },1000) } }, musicshang(){//上一首 let that=this; let ap = this.music[this.arynum-=1]; if (this.arynum<0) { this.arynum=this.music.length; this.axiosmu(ap);//发送上一首ID }else{ this.axiosmu(ap); setTimeout(function () {//利用定时器功能下一首时,自动播放 that.xia_bo(); },1000) } }, bo(){//点击播放按钮 let player = document.getElementById('xqt'); if(player.paused){ player.play(); $(".glyphicon-play").addClass("glyphicon-pause"); $(".in_img").addClass("dong"); $(".zan_an").removeClass("zan_an_au"); }else{ player.pause(); $(".glyphicon-play").removeClass("glyphicon-pause"); $(".in_img").removeClass("dong"); $(".zan_an").addClass("zan_an_au"); } }, xia_bo(){//点击下一首与上一首开始播放 let player = document.getElementById('xqt'); player.play(); $(".glyphicon-play").addClass("glyphicon-pause"); $(".in_img").addClass("dong"); $(".zan_an").removeClass("zan_an_au"); }, shou(){//展开与隐藏歌曲控件 $('#music_bo').animate({width:'toggle'},350); $('#back_img').animate({width:'toggle'},350); if(this.shou_s){ $('.ce_bun').animate({left:'0'},350); $('.ce_bun i').css({"transform":"rotate(180deg)","color":"#bd3a3a"}); this.shou_s =false; }else{ $('.ce_bun').animate({left:'310px'},350); $('.ce_bun i').css({"transform":"rotate(0deg)","color":"#fff"}); this.shou_s =true; } }, gelist(e){//歌单列表 var that =this;//解决this:null问题 if (this.gedan<=1) { for(let i=0;i<this.music.length;i++){ axios .get('https://api.imjad.cn/cloudmusic/?type=detail&id='+this.music[i]) .then(response => (//在数组的底部增加新元素 that.gedan.push({id:response.data.songs[0].id,name:response.data.songs[0].al.name}) )) } $("#ge_dan").slideToggle("slow"); }else{ $("#ge_dan").slideToggle("slow"); } $(".list_ge").toggleClass("red"); }, listfun(id){//点击列表的播放时 let that=this; this.axiosmu(id); } } } </script> <style scoped> .red{color:#bd3a3a!important;border:2px solid #bd3a3a!important;} body{ background-color: #E5F3FE; } .max_img{ width: 100px; height: 100px; overflow: hidden; border-radius: 88px; border: 2px solid #fff; } #back_img{ position: absolute; top: 400px; z-index: 1; width: 310px; filter: blur(20px); height: 200px; border-radius: 20px; overflow: hidden; } #back_img img{width: 108%;height: 100%;margin-top: -13%;} #music{margin-top: -20px;} .b_img{height: calc(100vh);width:100%;overflow: hidden;} .b_img img{width:100%} #music_bo{ padding: 10px; position: absolute; top: 400px; z-index: 2; width: 310px; height: 181px; overflow: hidden; border-top-right-radius: 20px; border-bottom-right-radius: 20px; } .title{background-color:#fff;} .title_h1,.title_info{color:#000; width:50%; float:left; overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1;} #xqt{ width: 158%; height: 26px; margin-left: -17%; border-radius: 15px; overflow: hidden; background-color: #fff; margin-top: 5%; } .in_left{width: 32%;float: left;} .in_img{width: 35%;float: left;overflow: hidden;max-height: 100px;} .in_right{width: 32%;float: left;} .dong{animation:myfirst 5s infinite linear;} @keyframes myfirst { 0% {transform:rotate(0deg);} 10% {transform:rotate(36deg);} 20% {transform:rotate(72deg);} 30% {transform:rotate(108deg);} 40% {transform:rotate(144deg);} 50% {transform:rotate(180deg);} 60% {transform:rotate(216deg);} 70% {transform:rotate(252deg);} 80% {transform:rotate(288deg);} 90% {transform:rotate(324deg);} 100% {transform:rotate(360deg);} } .zan_an_au{color:#bd3a3a!important;border:2px solid #bd3a3a!important;opacity: 1!important;} .in_img:hover >.zan_an{opacity: 1;transition: 1s;} .zan_an{ transition: 1s; opacity: 0; background: none; border: 2px solid #fff; position: relative; top: -76px; width: 50px; height: 50px; border-radius: 33px; color:#fff; } .no_button{ background: none; border: 2px solid #fff; font-size: 16px; border-radius: 15px; color: #fff; margin:10%; width: 28%; height: 28px; } .zan_an i{ font-size:22px; } .ce_bun{ position: absolute; top: 421px; left: 310px; z-index: 3; height: 50px; width: 29px; font-size: 19px; background: #5347478a; border: none; color: #fff; border-top-right-radius: 5px; border-bottom-right-radius: 5px; } #ge_dan{ display:none; position: absolute; top: 54px; right: 0px; width: 20%; } .listgun_ul{ overflow: auto; height: 600px; width:100%; padding: 0; } .listgun_ul a h4{ overflow: hidden; display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1; } .list_ge{ text-align: right; } </style>
JS 分块解释
data(){ return { music:[1364400123,480426313,1309896289,1344897943,1360740361,1426649237,1404906595,480353,2059056,29482234,1400256289,1406642934,1386259535,1409329655,1335580481,527957820,468176711,574566207,1316460171,536099160,534542079,1313354324,27890306,1328146041,31445554,552594869,471565190,480580003,425828896,29004400,514761281,536502758,1330348068,25706282,32083133,1460474276,4879345,524543708,427606780,1410840088,760037,492145159,461544312,507585220,411314681,465920383,21253966,28248872,1491585,1321385655,863046037,515601126,30212890,422132115,533465371,440208476,410802679,1313107065,438981337,465675773,5162502,17753288,29769734,21038748,409931224,534542015,18161816,2918954,463352636,26565006,19081573,28830412,26429346,466122460,21253958,444269135,440101136,418602088,19542383,455653437,27946894,468882985,19711382,29009655,466794339,32574252,3570196,1345018,461347998,36990266,28681438], bofangmu:'',//歌曲url muimg:'',//歌曲封面图片 gename:'',//歌曲名 usname:[],//歌手 gedan:[],//歌单 arynum:0,//获取上方歌曲ID shou_s:true//点击展开与隐藏 }; },
DATA
music 存放歌曲ID
这里存放的都是网易云歌曲的ID,鼠标移到到网页版的网易云可以看见ID
mounted(){ var that=this; this.axiosmu(this.music[this.arynum]); let player = document.getElementById('xqt'); player.ontimeupdate = function () { if(player.currentTime == player.duration){//判断当前歌曲是否播放完 that.musicxia();//执行下一首 } } },
mounted 生命周期函数
主要作用还是获取需要播放第一首歌的信息
player.ontimeupdate 用来判断当前页面歌曲死否播放完,自动播放下一首
axiosmu(numb){//获取歌曲信息 var that =this;//解决this:null问题 axios.all([this.getUserAccount(numb), this.getUserPermissions(numb)])//并发执行函数 .then(axios.spread(function (acct, perms) { that.bofangmu = acct.data.data[0].url;//获取歌的链接 that.muimg =perms.data.songs[0].al.picUrl;//获取图片链接 that.gename =perms.data.songs[0].al.name;//获取歌名 for(let i=0;i<perms.data.songs[0].ar.length;i++){//循环获取歌手 that.usname[i]=perms.data.songs[0].ar[i].name; } })); }
由于歌曲信息不是放在同一个API中所以需要同时获取多个API接口,通过 axios.all的 并发功能获取
演唱歌手也不是只有一位,所以循环获得
getUserAccount(e) {return axios.get('https://api.imjad.cn/cloudmusic/?id='+e);},//获取音乐链接 getUserPermissions(e) {return axios.get('https://api.imjad.cn/cloudmusic/?type=detail&id='+e);},//获取图像
实际获取API信息的是这俩函数
musicxia(){//下一首 let ap = this.music[this.arynum+=1]; if(this.arynum>=this.music.length){ this.arynum=0; this.axiosmu(ap);//发送下一首ID }else{ let that=this; this.axiosmu(ap); setTimeout(function () {//利用定时器功能下一首时,自动播放 that.xia_bo(); ,1000) } }, musicshang(){//上一首 let that=this; let ap = this.music[this.arynum-=1]; if (this.arynum<0) { this.arynum=this.music.length; this.axiosmu(ap);//发送上一首ID }else{ this.axiosmu(ap); setTimeout(function () {//利用定时器功能下一首时,自动播放 that.xia_bo(); },1000) } },
上一首,获取歌曲ID列表的总长度来判定上一首歌的ID,下一首的功能也是如此
bo(){//点击播放按钮 let player = document.getElementById('xqt'); if(player.paused){ player.play(); $(".glyphicon-play").addClass("glyphicon-pause"); $(".in_img").addClass("dong"); $(".zan_an").removeClass("zan_an_au"); }else{ player.pause(); $(".glyphicon-play").removeClass("glyphicon-pause"); $(".in_img").removeClass("dong"); $(".zan_an").addClass("zan_an_au"); } }, xia_bo(){//点击下一首与上一首开始播放 let player = document.getElementById('xqt'); player.play(); $(".glyphicon-play").addClass("glyphicon-pause"); $(".in_img").addClass("dong"); $(".zan_an").removeClass("zan_an_au"); },
bo() 是歌曲图片上面那个播放暂停按钮
xia_bo()是点击下一首与上一首时判定的音乐播放
shou(){//展开与隐藏歌曲控件 $('#music_bo').animate({width:'toggle'},350); $('#back_img').animate({width:'toggle'},350); if(this.shou_s){ $('.ce_bun').animate({left:'0'},350); $('.ce_bun i').css({"transform":"rotate(180deg)","color":"#bd3a3a"}); this.shou_s =false; }else{ $('.ce_bun').animate({left:'310px'},350); $('.ce_bun i').css({"transform":"rotate(0deg)","color":"#fff"}); this.shou_s =true; } }, gelist(e){//歌单列表 var that =this;//解决this:null问题 if (this.gedan<=1) { for(let i=0;i<this.music.length;i++){ axios .get('https://api.imjad.cn/cloudmusic/?type=detail&id='+this.music[i]) .then(response => (//在数组的底部增加新元素 that.gedan.push({id:response.data.songs[0].id,name:response.data.songs[0].al.name}) )) } $("#ge_dan").slideToggle("slow"); }else{ $("#ge_dan").slideToggle("slow"); } $(".list_ge").toggleClass("red"); }, listfun(id){//点击列表的播放时 this.axiosmu(id); }
shou()展示与隐藏音乐播放控件的函数
gelist()中使用.push将获取到的歌曲数据存放到对应的内容中!
listfun()对展示出的歌曲列表点击进行切换歌曲
总结(重点记录)
1:利用 player.paused 可知道当前音乐是否在播放
let player = document.getElementById(‘xqt’);
if(player.paused){
暂停中
}else{
播放中
}
2:音乐播放
player.play();
3:音乐暂停
player.pause();
4:为某元素增加class
$(“.glyphicon-play”).addClass(“glyphicon-pause”);
5:为某元素移除class
$(“.zan_an”).removeClass(“zan_an_au”);
6:利用只执行一次的延迟定时器达到下一首播放功能
setTimeout(function () {that.xia_bo();},1000)
7:axios 通过API获取歌曲信息并整合
axios.all([this.getUserAccount(numb), this.getUserPermissions(numb)])//并发获取
8:将获取到的数据存放在数组中的对象
that.gedan.push({id:response.data.songs[0].id,name:response.data.songs[0].al.name})